LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-29-2020, 02:41 PM   #16
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869

I've just found an older code of mine that contains this bit:
Code:
        const ASN1_TIME *at;

        at= X509_get0_notBefore (cert);
        if (at) {
            struct tm tm;

            memset (&tm, 0, sizeof *&tm);
            ASN1_TIME_to_tm (at, &tm);
            into->tNotBefore= timegm (&tm);
        }
Also I created a `timegm` implementation for AIX (which doesn't have it):
Code:
/* aix-timegm.c */

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

time_t timegm (struct tm *tm);
time_t timegm (struct tm *tm)
{
    int year, ytmp, dtmp, ytmpe, dtmpe;
    int isleapyear;
    static int msum [2][12] = {
        { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},       /* normal years */
        { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}        /* leap years */
    };
    static int mlen [2][12] = {
        { 31, 28, 31, 30,  31,  30,  31,  31,  30,  31,  30, 31},
        { 31, 29, 31, 30,  31,  30,  31,  31,  30,  31,  30, 31}
    };
    long long t;

    if (!tm) return -1;

    year = tm->tm_year+1900;
    isleapyear= (year%4==0) - (year%100==0) + (year%400==0);

    if (year<1600  || year>2400  ||
        tm->tm_mon<0  || tm->tm_mon>11 ||
        tm->tm_mday<1 || tm->tm_mday>mlen[isleapyear][tm->tm_mon] ||
        tm->tm_hour<0 || tm->tm_hour>23 ||
        tm->tm_min<0  || tm->tm_min>59 ||
        tm->tm_min<0  || tm->tm_sec>59) return -1;

    ytmp = year - 1601;
    dtmp = ytmp*365 + ytmp/4 - ytmp/100 + ytmp/400;

    ytmpe = 1970 - 1601;
    dtmpe = ytmpe*365 + ytmpe/4 - ytmpe/100 + ytmpe/400; /* = 134685 + 92 - 3 + 0 = 134774 */

    t  = dtmp - dtmpe;
    t += msum[isleapyear][tm->tm_mon];
    t += tm->tm_mday-1;

    tm->tm_wday = (t+4)%7;/* 0..6=Sun..Sat; adding 4 to adjust 1970.01.01.=Thursday; */
    if (tm->tm_wday<0) tm->tm_wday += 7;
    tm->tm_yday = msum[isleapyear][tm->tm_mon] + tm->tm_mday-1;
    tm->tm_isdst= 0;

    t  = t*24 + tm->tm_hour;
    t  = t*60 + tm->tm_min;
    t  = t*60 + tm->tm_sec;

#if LONG_MAX == 2147483647L
    if (t<LONG_MIN || t>LONG_MAX) {
        t= -1;
    }
#endif

    return t;
}
 
3 members found this post helpful.
Old 10-29-2020, 03:12 PM   #17
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
How about declaring extern long timezone and then adjusting t_of_day by subtracting adding the value in timezone?

edit: in fact, it looks like time.h defines it already so you don't even need to declare.

edot2: actually, mktime() will return a t_of_day that will have the assumed timezone subtracted, so you need to put it back on if the original values were already specified in GMT0, so adding, not subtracting when you do it this way around.

Something like this maybe?
Code:
#include <time.h>
// extern long timezone;


time_t mktimegm(struct tm *tm_gmt)
{
    time_t t;
    t = mktime(tm_gmt);
    
    return ( t == -1 ) ? t : t + timezone ;
}
edit3: Ah nutz! Apparently mktime() will still adjust for DST, even if you set isdst to 0 before calling, so looks like this is too simplistic and one also needs to adjust for dst. Maybe temporarily setting the timezone to GMT was the better idea after all. Or, just write your own routines like Neve' did.

Last edited by GazL; 10-29-2020 at 04:34 PM.
 
Old 10-29-2020, 03:25 PM   #18
linxbee
Member
 
Registered: Jan 2020
Distribution: RHEL,CENTOS, Ubuntu
Posts: 52

Original Poster
Rep: Reputation: Disabled
Thumbs up

cannot thank enough @NevemTeve , looks like this is what i need , have to do some tests with different dates.

looks like you are calculating exact number days that are elapsed from 1900 and then multiplying with 24*60*60.


Well i dont get some part of the code, what is the purpose of this part?

Code:
// is it number of days in nonleap years ??
ytmp = year - 1601;
dtmp = ytmp*365 + ytmp/4 - ytmp/100 + ytmp/400;

// is it number of days in leap years ??
ytmpe = 1970 - 1601;
dtmpe = ytmpe*365 + ytmpe/4 - ytmpe/100 + ytmpe/400; /* = 134685 + 92 - 3 + 0 = 134774 */
https://www.linuxquestions.org/quest...s_lq/icon7.gif
 
Old 10-29-2020, 03:41 PM   #19
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
If I remember correctly (file dated 2018-07-24), this program uses 1601-01-01 as base, as it is the start of an 400-year period of leap-years, so the 'days passed before the actual year (since the base)' can be calculated as (year*365)+(year/4)-(year/100)+(year/400).

Then this has to be converted to the unix-epoch, that's where the number of days between 1601-01-01 and 1970-01-01 matters (dtmpe=134774)
 
1 members found this post helpful.
Old 10-29-2020, 03:42 PM   #20
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
If I remember correctly (file dated 2018-07-24), this program uses 1601-01-01 as base, as it is the start of an 400-year period of leap-years, so the 'days passed before the actual year (since the base)' can be calculated as (year*365)+(year/4)-(year/100)+(year/400).

Then this has to be converted to the unix-epoch, that's where the number of days between 1601-01-01 and 1970-01-01 matters (dtmpe=134774)
 
Old 01-02-2021, 01:07 AM   #21
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
uploaded here:
https://github.com/lzsiga/timegm
 
  


Reply

Tags
c programming, datetime, linux



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Timezone in reverse. GMT+4 works as GMT-4 Lockywolf Slackware 3 05-20-2012 05:25 PM
MQ LINUX vs MQ Unix Conversion Differences - LINUX Conversion Issues catch93 Linux - Newbie 4 11-03-2011 09:10 PM
PHP Time before Unix Epoch? wh33t Programming 2 08-29-2006 01:32 PM
Convert CCYYMMDDhhmmss to Unix Epoch. unreal128 Linux - General 1 07-22-2006 07:06 PM
The End of the UNIX Epoch oulevon Programming 10 11-22-2003 02:42 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:34 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration