using mktime()

Discussion in 'C Programming' started by John Hanley, Feb 12, 2005.

  1. John Hanley

    John Hanley Guest

    I created a function that breaks down a date into broken down time, I
    subtract a certain number of seconds from that, then use mktime() to
    recompute the calendar time.

    It works basically except every so often, I get the date 060207 (Feb 7,
    2006) which is obviously not correct. When it does this it always gives me
    this date.

    I tracked it down to my mktime() call, when I get to a certain date, mktime
    returns a number in 4000000000, when it should return a number in
    1000000000. But I am not sure why. The variable in my tm struct all have
    the correct date, but mktime returns this.

    It is happening to me when the date I am changing is: 040727 but it has done
    this on others as well.

    I am thinking that something goes wrong in mktime() to cause it to return
    some default number. Perhaps something wrong in one of my time_broken
    members and then it gets past to mktime?

    Suggestions? Thanks a bunch!

    Here's my code:

    int adjust_time()
    {
    struct tm time_broken; /* time in broken time */
    struct tm tb; /* adjusted time */
    time_t time_calendar=0; /* calendar time as a long int */
    int sec,min,hour,mday,mon,year;
    long int dt; /* temp variables */
    int tm;


    /* if CHG_TIME==0, no conversion necessary */
    if(CHG_TIME==0)
    {
    return 1;
    }

    /* parse out time & date info */
    sec=0;
    min=TIME%100;
    hour=TIME/100;
    mday=DATE%100;
    mon=((DATE%10000)/100)-1;

    /* year must be represented as years since 1900 */
    /* If the year is < 40, we assume it's in 2000's */
    /* If the year is >= 40, we assume it's in 1900's */
    year=(DATE/10000);
    if(year<40)
    year=year+100;


    /* create the struct tm */
    time_broken.tm_sec=sec;
    time_broken.tm_min=min;
    time_broken.tm_hour=hour;
    time_broken.tm_mday=mday;
    time_broken.tm_mon=mon;
    time_broken.tm_year=year;

    /* get the number of seconds since
    * Jan 1, 1970 */
    time_calendar=mktime(&time_broken);

    /* subtract CHGTIME from calendar time_t date */
    time_calendar=time_calendar-(CHG_TIME*60);
    tb=*(gmtime(&time_calendar));

    /* calculate new time */
    tm=(tb.tm_hour*100)+tb.tm_min;

    /* calculate new date */
    dt=( ((tb.tm_year%100)*10000) + ((tb.tm_mon+1)*100) + (tb.tm_mday) );

    /* return new time & date */
    TIME=tm;
    DATE=dt;

    return 0;
    }
     
    John Hanley, Feb 12, 2005
    #1
    1. Advertising

  2. John Hanley

    Mike Wahler Guest

    "John Hanley" <> wrote in message
    news:...
    > I created a function that breaks down a date into broken down time, I
    > subtract a certain number of seconds from that, then use mktime() to
    > recompute the calendar time.
    >
    > It works basically except every so often, I get the date 060207 (Feb 7,
    > 2006) which is obviously not correct. When it does this it always gives

    me
    > this date.
    >
    > I tracked it down to my mktime() call, when I get to a certain date,

    mktime
    > returns a number in 4000000000, when it should return a number in
    > 1000000000. But I am not sure why. The variable in my tm struct all have
    > the correct date, but mktime returns this.
    >
    > It is happening to me when the date I am changing is: 040727 but it has

    done
    > this on others as well.
    >
    > I am thinking that something goes wrong in mktime() to cause it to return
    > some default number. Perhaps something wrong in one of my time_broken
    > members and then it gets past to mktime?
    >
    > Suggestions? Thanks a bunch!
    >
    > Here's my code:


    You don't provide definitions for 'CHG_TIME', 'TIME', or
    'DATE', so it's impossible to diagnose your problem. Try
    posting a complete compilable example that demonstrates
    the problem.

    I don't know if it's an issue or not, but your reference to
    dates above in the form of e.g. 040727 causes me to caution
    you that if that's a literal numeric value, note that any
    numeric literal whose first digit is zero is interpreted
    by the compiler as an octal (base eight) representation.

    -Mike
     
    Mike Wahler, Feb 12, 2005
    #2
    1. Advertising

  3. John Hanley

    j Guest

    "John Hanley" <> wrote in message
    news:...
    > I created a function that breaks down a date into broken down time, I
    > subtract a certain number of seconds from that, then use mktime() to
    > recompute the calendar time.
    >
    > It works basically except every so often, I get the date 060207 (Feb 7,
    > 2006) which is obviously not correct. When it does this it always gives

    me
    > this date.
    >
    > I tracked it down to my mktime() call, when I get to a certain date,

    mktime
    > returns a number in 4000000000, when it should return a number in
    > 1000000000. But I am not sure why. The variable in my tm struct all have
    > the correct date, but mktime returns this.
    >
    > It is happening to me when the date I am changing is: 040727 but it has

    done
    > this on others as well.
    >
    > I am thinking that something goes wrong in mktime() to cause it to return
    > some default number. Perhaps something wrong in one of my time_broken
    > members and then it gets past to mktime?
    >
    > Suggestions? Thanks a bunch!
    >
    > Here's my code:
    >
    > int adjust_time()
    > {
    > struct tm time_broken; /* time in broken time */
    > struct tm tb; /* adjusted time */
    > time_t time_calendar=0; /* calendar time as a long int */
    > int sec,min,hour,mday,mon,year;
    > long int dt; /* temp variables */
    > int tm;
    >
    >
    > /* if CHG_TIME==0, no conversion necessary */
    > if(CHG_TIME==0)
    > {
    > return 1;
    > }
    >
    > /* parse out time & date info */
    > sec=0;
    > min=TIME%100;
    > hour=TIME/100;
    > mday=DATE%100;
    > mon=((DATE%10000)/100)-1;
    >
    > /* year must be represented as years since 1900 */
    > /* If the year is < 40, we assume it's in 2000's */
    > /* If the year is >= 40, we assume it's in 1900's */
    > year=(DATE/10000);
    > if(year<40)
    > year=year+100;
    >
    >
    > /* create the struct tm */
    > time_broken.tm_sec=sec;
    > time_broken.tm_min=min;
    > time_broken.tm_hour=hour;
    > time_broken.tm_mday=mday;
    > time_broken.tm_mon=mon;
    > time_broken.tm_year=year;
    >
    > /* get the number of seconds since
    > * Jan 1, 1970 */
    > time_calendar=mktime(&time_broken);


    You never assign a meaningful value to member ``tm_isdst''.
    mktime thus uses an indeterminate value and the consequence
    is undefined behaviour.



    --
    j
     
    j, Feb 12, 2005
    #3
  4. John Hanley

    Al Bowers Guest

    John Hanley wrote:
    > I created a function that breaks down a date into broken down time, I
    > subtract a certain number of seconds from that, then use mktime() to
    > recompute the calendar time.
    >
    > It works basically except every so often, I get the date 060207 (Feb 7,
    > 2006) which is obviously not correct. When it does this it always gives me
    > this date.
    >
    > I tracked it down to my mktime() call, when I get to a certain date, mktime
    > returns a number in 4000000000, when it should return a number in
    > 1000000000. But I am not sure why. The variable in my tm struct all have
    > the correct date, but mktime returns this.
    >
    > It is happening to me when the date I am changing is: 040727 but it has done
    > this on others as well.
    >
    > I am thinking that something goes wrong in mktime() to cause it to return
    > some default number. Perhaps something wrong in one of my time_broken
    > members and then it gets past to mktime?
    >
    > Suggestions? Thanks a bunch!
    >
    > Here's my code:


    The code is not complete and it is not easy to follow the logic.
    But I see you are making some errors. Apparently, you are
    assuming that type time_t is type long representing seconds.
    Standard C does not specify this to be fact. The Standard
    only specifies that time_t be an arithmetic time capable of
    representing time. And, it does not specify anything on
    its instrumentality. So, to be portable, the code must not
    assume the type to be type long and the values representing
    seconds. To get around this, Standard C provides functions
    that will allow you to manipulate time. So, to correct
    your function adjust_time, you will need to convert the
    time_t value to broken down time and the adjust the struct
    member tm_sec in the number of seconds. Then call function
    mktime to generate a new time_t value.


    Another problem: check your return values.
    You did not check the return value
    of your mktime function. time_t's range of dates is limited.
    Function mktime will return (time_t)-1 should it be uncapable
    of representing that date. I can't be sure, but the values
    you are getting in the range of 4000000000 may be result of
    function mktime returning a (time_t)-1 value.

    An example:

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

    time_t AdjustTime(time_t tvalue, int secs)
    {
    struct tm *tp;
    time_t ret;

    if((ret = (tvalue != (time_t)-1)))
    {
    tp = localtime(&tvalue);
    if(secs > INT_MAX - tp->tm_sec)
    ret = (time_t)-1;
    else
    {
    tp->tm_sec+=secs;
    tp->tm_isdst = -1;
    ret = mktime(tp);
    }
    }
    return ret;
    }

    int main(void)
    {
    time_t date;
    struct tm t;

    /* make a time_t value for 25DEC2005 12:00:00 */
    t.tm_year = 2005-1900;
    t.tm_mon = 11;
    t.tm_mday = 25;
    t.tm_hour = 12;
    t.tm_min = t.tm_sec = t.tm_isdst = 0;

    if((date = mktime(&t)) == (time_t)-1)
    puts("Time is not available");
    else
    {
    printf("date represents %s"
    "Attemping to subtract 60 secs\n",ctime(&date));
    if((date = AdjustTime(date, -60)) != (time_t)-1)
    printf("The new date is %s",ctime(&date));
    else puts("Time for the new date is unavailable");
    }
    return 0;
    }


    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
     
    Al Bowers, Feb 12, 2005
    #4
  5. John Hanley

    John Hanley Guest

    > The code is not complete and it is not easy to follow the logic.
    > But I see you are making some errors. Apparently, you are
    > assuming that type time_t is type long representing seconds.


    you're right, that was what I was assuming.

    > Standard C does not specify this to be fact. The Standard
    > only specifies that time_t be an arithmetic time capable of
    > representing time. And, it does not specify anything on
    > its instrumentality. So, to be portable, the code must not
    > assume the type to be type long and the values representing
    > seconds. To get around this, Standard C provides functions
    > that will allow you to manipulate time. So, to correct
    > your function adjust_time, you will need to convert the
    > time_t value to broken down time and the adjust the struct
    > member tm_sec in the number of seconds. Then call function
    > mktime to generate a new time_t value.


    I see what you mean. My problem is that I am actually trying to adjust
    minutes (from 1 to 59) and subtract the CHG_TIME number from the number of
    minutes. However, if my date is Jan 1, 2000 at 00:00, by changing the
    minutes, the hour, day, month, & year all have to change as well. That's
    why I thought if I could get the time_t value as calendar time, subtract
    from it number of minutes*60 (the correct number of seconds), and use
    mktime(), I would get the adjusted date (the date-CHG_TIME).

    I was under the assumption that the calendar time is the number of seconds
    since Jan 1, 1970, and my subtracting so many seconds from that value and
    calling mktime(), I would get an earlier date.

    So if I were to adjust the broken time instead of the calendar time, how
    would I handle the change in minutes, hour, date, month year without having
    to do it manually?

    Thanks so much for the help! I really appreciate it!

    John


    >
    >
    > Another problem: check your return values.
    > You did not check the return value
    > of your mktime function. time_t's range of dates is limited.
    > Function mktime will return (time_t)-1 should it be uncapable
    > of representing that date. I can't be sure, but the values
    > you are getting in the range of 4000000000 may be result of
    > function mktime returning a (time_t)-1 value.
    >
    > An example:
    >
    > #include <stdio.h>
    > #include <time.h>
    > #include <limits.h>
    >
    > time_t AdjustTime(time_t tvalue, int secs)
    > {
    > struct tm *tp;
    > time_t ret;
    >
    > if((ret = (tvalue != (time_t)-1)))
    > {
    > tp = localtime(&tvalue);
    > if(secs > INT_MAX - tp->tm_sec)
    > ret = (time_t)-1;
    > else
    > {
    > tp->tm_sec+=secs;
    > tp->tm_isdst = -1;
    > ret = mktime(tp);
    > }
    > }
    > return ret;
    > }
    >
    > int main(void)
    > {
    > time_t date;
    > struct tm t;
    >
    > /* make a time_t value for 25DEC2005 12:00:00 */
    > t.tm_year = 2005-1900;
    > t.tm_mon = 11;
    > t.tm_mday = 25;
    > t.tm_hour = 12;
    > t.tm_min = t.tm_sec = t.tm_isdst = 0;
    >
    > if((date = mktime(&t)) == (time_t)-1)
    > puts("Time is not available");
    > else
    > {
    > printf("date represents %s"
    > "Attemping to subtract 60 secs\n",ctime(&date));
    > if((date = AdjustTime(date, -60)) != (time_t)-1)
    > printf("The new date is %s",ctime(&date));
    > else puts("Time for the new date is unavailable");
    > }
    > return 0;
    > }
    >
    >
    > --
    > Al Bowers
    > Tampa, Fl USA
    > mailto: (remove the x to send email)
    > http://www.geocities.com/abowers822/
    >
     
    John Hanley, Feb 12, 2005
    #5
  6. John Hanley

    John Hanley Guest

    "j" <> wrote in message
    news:RUhPd.889$...
    >
    > "John Hanley" <> wrote in message
    > news:...
    > > I created a function that breaks down a date into broken down time, I
    > > subtract a certain number of seconds from that, then use mktime() to
    > > recompute the calendar time.
    > >
    > > It works basically except every so often, I get the date 060207 (Feb 7,
    > > 2006) which is obviously not correct. When it does this it always gives

    > me
    > > this date.
    > >
    > > I tracked it down to my mktime() call, when I get to a certain date,

    > mktime
    > > returns a number in 4000000000, when it should return a number in
    > > 1000000000. But I am not sure why. The variable in my tm struct all

    have
    > > the correct date, but mktime returns this.
    > >
    > > It is happening to me when the date I am changing is: 040727 but it has

    > done
    > > this on others as well.
    > >
    > > I am thinking that something goes wrong in mktime() to cause it to

    return
    > > some default number. Perhaps something wrong in one of my time_broken
    > > members and then it gets past to mktime?
    > >
    > > Suggestions? Thanks a bunch!
    > >
    > > Here's my code:
    > >
    > > int adjust_time()
    > > {
    > > struct tm time_broken; /* time in broken time */
    > > struct tm tb; /* adjusted time */
    > > time_t time_calendar=0; /* calendar time as a long int */
    > > int sec,min,hour,mday,mon,year;
    > > long int dt; /* temp variables */
    > > int tm;
    > >
    > >
    > > /* if CHG_TIME==0, no conversion necessary */
    > > if(CHG_TIME==0)
    > > {
    > > return 1;
    > > }
    > >
    > > /* parse out time & date info */
    > > sec=0;
    > > min=TIME%100;
    > > hour=TIME/100;
    > > mday=DATE%100;
    > > mon=((DATE%10000)/100)-1;
    > >
    > > /* year must be represented as years since 1900 */
    > > /* If the year is < 40, we assume it's in 2000's */
    > > /* If the year is >= 40, we assume it's in 1900's */
    > > year=(DATE/10000);
    > > if(year<40)
    > > year=year+100;
    > >
    > >
    > > /* create the struct tm */
    > > time_broken.tm_sec=sec;
    > > time_broken.tm_min=min;
    > > time_broken.tm_hour=hour;
    > > time_broken.tm_mday=mday;
    > > time_broken.tm_mon=mon;
    > > time_broken.tm_year=year;
    > >
    > > /* get the number of seconds since
    > > * Jan 1, 1970 */
    > > time_calendar=mktime(&time_broken);

    >
    > You never assign a meaningful value to member ``tm_isdst''.
    > mktime thus uses an indeterminate value and the consequence
    > is undefined behaviour.


    Very good eye. I set tm_isdst to -1 each time (as I have no idea of DST on
    any of these dates) and it seemed to work great.

    Now, I was looking at the next reply from Al Bowers' and he mentioned that
    my assumption of time_t calendar time as being actual seconds, my be an
    incorrect assumption.

    What I have been doing is getting the calendar time from broken time,
    subtracting so many seconds from it (which is actually equivalent to 1 to 59
    minutes) and converting the calendar time back to broken time. The reason I
    do it this way is so that if it's Jan 1, 2000 at 00:00, subtracting 45
    minutes (45*60 seconds) from this gets me an entirely new date, not just a
    change in minutes.

    Is this approach ok, or will I run into any future undefined behaviour?

    Thanks so much for the help! I very much appreciate it!

    Best regards,
    John
     
    John Hanley, Feb 12, 2005
    #6
  7. John Hanley

    John Hanley Guest

    > I see what you mean. My problem is that I am actually trying to adjust
    > minutes (from 1 to 59) and subtract the CHG_TIME number from the number of
    > minutes. However, if my date is Jan 1, 2000 at 00:00, by changing the
    > minutes, the hour, day, month, & year all have to change as well. That's
    > why I thought if I could get the time_t value as calendar time, subtract
    > from it number of minutes*60 (the correct number of seconds), and use
    > mktime(), I would get the adjusted date (the date-CHG_TIME).


    sorry, that should read "and use gmtime(), I would get the adjusted date..."

    >
    > I was under the assumption that the calendar time is the number of seconds
    > since Jan 1, 1970, and my subtracting so many seconds from that value and
    > calling mktime(), I would get an earlier date.


    here too. "...and calling gmtime(), i would get an earlier date".

    sorry for the confusion.

    >
    > So if I were to adjust the broken time instead of the calendar time, how
    > would I handle the change in minutes, hour, date, month year without

    having
    > to do it manually?
    >
    > Thanks so much for the help! I really appreciate it!
    >
    > John
    >
    >
    > >
    > >
    > > Another problem: check your return values.
    > > You did not check the return value
    > > of your mktime function. time_t's range of dates is limited.
    > > Function mktime will return (time_t)-1 should it be uncapable
    > > of representing that date. I can't be sure, but the values
    > > you are getting in the range of 4000000000 may be result of
    > > function mktime returning a (time_t)-1 value.
    > >
    > > An example:
    > >
    > > #include <stdio.h>
    > > #include <time.h>
    > > #include <limits.h>
    > >
    > > time_t AdjustTime(time_t tvalue, int secs)
    > > {
    > > struct tm *tp;
    > > time_t ret;
    > >
    > > if((ret = (tvalue != (time_t)-1)))
    > > {
    > > tp = localtime(&tvalue);
    > > if(secs > INT_MAX - tp->tm_sec)
    > > ret = (time_t)-1;
    > > else
    > > {
    > > tp->tm_sec+=secs;
    > > tp->tm_isdst = -1;
    > > ret = mktime(tp);
    > > }
    > > }
    > > return ret;
    > > }
    > >
    > > int main(void)
    > > {
    > > time_t date;
    > > struct tm t;
    > >
    > > /* make a time_t value for 25DEC2005 12:00:00 */
    > > t.tm_year = 2005-1900;
    > > t.tm_mon = 11;
    > > t.tm_mday = 25;
    > > t.tm_hour = 12;
    > > t.tm_min = t.tm_sec = t.tm_isdst = 0;
    > >
    > > if((date = mktime(&t)) == (time_t)-1)
    > > puts("Time is not available");
    > > else
    > > {
    > > printf("date represents %s"
    > > "Attemping to subtract 60 secs\n",ctime(&date));
    > > if((date = AdjustTime(date, -60)) != (time_t)-1)
    > > printf("The new date is %s",ctime(&date));
    > > else puts("Time for the new date is unavailable");
    > > }
    > > return 0;
    > > }
    > >
    > >
    > > --
    > > Al Bowers
    > > Tampa, Fl USA
    > > mailto: (remove the x to send email)
    > > http://www.geocities.com/abowers822/
    > >

    >
    >
     
    John Hanley, Feb 12, 2005
    #7
  8. John Hanley

    Al Bowers Guest

    John Hanley wrote:

    >>The code is not complete and it is not easy to follow the logic.
    >>But I see you are making some errors. Apparently, you are
    >>assuming that type time_t is type long representing seconds.

    >
    >
    > you're right, that was what I was assuming.
    >
    >
    >>Standard C does not specify this to be fact. The Standard
    >>only specifies that time_t be an arithmetic time capable of
    >>representing time. And, it does not specify anything on
    >>its instrumentality. So, to be portable, the code must not
    >>assume the type to be type long and the values representing
    >>seconds. To get around this, Standard C provides functions
    >>that will allow you to manipulate time. So, to correct
    >>your function adjust_time, you will need to convert the
    >>time_t value to broken down time and the adjust the struct
    >>member tm_sec in the number of seconds. Then call function
    >>mktime to generate a new time_t value.

    >
    >
    > I see what you mean. My problem is that I am actually trying to adjust
    > minutes (from 1 to 59) and subtract the CHG_TIME number from the number of
    > minutes. However, if my date is Jan 1, 2000 at 00:00, by changing the
    > minutes, the hour, day, month, & year all have to change as well. That's
    > why I thought if I could get the time_t value as calendar time, subtract
    > from it number of minutes*60 (the correct number of seconds), and use
    > mktime(), I would get the adjusted date (the date-CHG_TIME).
    >
    > I was under the assumption that the calendar time is the number of seconds
    > since Jan 1, 1970, and my subtracting so many seconds from that value and
    > calling mktime(), I would get an earlier date.
    >


    You should not make this assumption if you are writing portable Standard
    C code.

    > So if I were to adjust the broken time instead of the calendar time, how
    > would I handle the change in minutes, hour, date, month year without having
    > to do it manually?
    >

    You will need to update the members in the struct tm. When you call
    function mktime all values will be normalized and put in range. For
    example you can substract 2 min by just modifying the tm_sec -= 120
    or you can substract from tm_min -= 2. Both are valid.

    Example:

    #include <stdio.h>
    #include <time.h>

    int main(void)
    {
    time_t date;
    struct tm t;

    /* make a time_t value for 25DEC2005 12:00:00 */
    t.tm_year = 2005-1900;
    t.tm_mon = 11;
    t.tm_mday = 25;
    t.tm_hour = 12;
    t.tm_min = t.tm_sec = t.tm_isdst = 0;

    /* substract 120 sec (2 minutes) */
    if((date = mktime(&t)) != (time_t)-1)
    {
    printf("The Date is: %s",ctime(&date));
    t.tm_sec -= 120;
    t.tm_isdst = -1;
    if((date = mktime(&t)) != (time_t)-1)
    {
    printf("Subst. 2min: %s",ctime(&date));
    t = *gmtime(&date);
    t.tm_isdst = -1;
    if((date = mktime(&t)) != (time_t)-1)
    printf("GMT date is: %s",ctime(&date));
    }
    else puts("Time unavailable");
    }
    else puts("Time unavailable");
    return 0;
    }




    > Thanks so much for the help! I really appreciate it!
    >
    > John
    >
    >
    >
    >>
    >>Another problem: check your return values.
    >>You did not check the return value
    >>of your mktime function. time_t's range of dates is limited.
    >>Function mktime will return (time_t)-1 should it be uncapable
    >>of representing that date. I can't be sure, but the values
    >>you are getting in the range of 4000000000 may be result of
    >>function mktime returning a (time_t)-1 value.
    >>
    >>An example:
    >>
    >>#include <stdio.h>
    >>#include <time.h>
    >>#include <limits.h>
    >>
    >>time_t AdjustTime(time_t tvalue, int secs)
    >>{
    >> struct tm *tp;
    >> time_t ret;
    >>
    >> if((ret = (tvalue != (time_t)-1)))
    >> {
    >> tp = localtime(&tvalue);
    >> if(secs > INT_MAX - tp->tm_sec)
    >> ret = (time_t)-1;
    >> else
    >> {
    >> tp->tm_sec+=secs;
    >> tp->tm_isdst = -1;
    >> ret = mktime(tp);
    >> }
    >> }
    >> return ret;
    >>}
    >>
    >>int main(void)
    >>{
    >> time_t date;
    >> struct tm t;
    >>
    >> /* make a time_t value for 25DEC2005 12:00:00 */
    >> t.tm_year = 2005-1900;
    >> t.tm_mon = 11;
    >> t.tm_mday = 25;
    >> t.tm_hour = 12;
    >> t.tm_min = t.tm_sec = t.tm_isdst = 0;
    >>
    >> if((date = mktime(&t)) == (time_t)-1)
    >> puts("Time is not available");
    >> else
    >> {
    >> printf("date represents %s"
    >> "Attemping to subtract 60 secs\n",ctime(&date));
    >> if((date = AdjustTime(date, -60)) != (time_t)-1)
    >> printf("The new date is %s",ctime(&date));
    >> else puts("Time for the new date is unavailable");
    >> }
    >> return 0;
    >>}
    >>
    >>
    >>--
    >>Al Bowers
    >>Tampa, Fl USA
    >>mailto: (remove the x to send email)
    >>http://www.geocities.com/abowers822/
    >>

    >
    >
    >


    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
     
    Al Bowers, Feb 12, 2005
    #8
  9. On Sat, 12 Feb 2005 10:00:16 -0700, John Hanley
    <> wrote:

    > Very good eye. I set tm_isdst to -1 each time (as I have no idea of DST on
    > any of these dates) and it seemed to work great.


    If you want it to assume local time, that is the correct thing to do.
    To assume GMT (UT) set that field to zero (if you are manipulating dates
    it is easier in GMT, convert to and from local time only when doing I/O).

    > Now, I was looking at the next reply from Al Bowers' and he mentioned that
    > my assumption of time_t calendar time as being actual seconds, my be an
    > incorrect assumption.


    Correct. It could be a floating point number of nanofortnights since the
    Big Bang for all you know. The only thing guaranteed is that (time_t)-1
    is an error value. It might not even be a linear representation, it
    could use bit fields for years, months, days, hours, minutes, seconds
    etc. (like the MSDOS filetimes did). The function difftime() will do
    whatever magic is needed to return the difference of two time_t values
    as a double number of seconds, localtime() and gmtime() will break it
    down into the structure, and mktime() will create a time_t from the
    structure.

    > What I have been doing is getting the calendar time from broken time,
    > subtracting so many seconds from it (which is actually equivalent to 1 to 59
    > minutes) and converting the calendar time back to broken time. The reason I
    > do it this way is so that if it's Jan 1, 2000 at 00:00, subtracting 45
    > minutes (45*60 seconds) from this gets me an entirely new date, not just a
    > change in minutes.
    >
    > Is this approach ok, or will I run into any future undefined behaviour?


    It will probably work until something changes. It is, however undefined
    in the C standard (IIRC POSIX.1 defines it for systems which comply with
    that standard).

    The correct way to manipulate times is to use the broken-down structure,
    mess about with the fields and make that back into a time_t using
    mktime(). For instance, to get the time 2:23:45 from now use:

    time_t now = time(NULL);
    time_t then;
    struct tm tt = *gmtime(&now);
    tt.tm_hour += 2;;
    tt.tm_min += 23;
    tt.tm_sec += 45;
    then = mktime(&tt);

    (that's a snippet, not a complete program -- some of the pedants will
    complain about not including headers and the like if I don't say that).

    Unfortunately, the C standard doesn't say anything about the allowable
    ranges of the fields, except that they are of type int and the normal
    ranges are what you would expect. In particular, it doesn't say whether
    negative values have the correct effect, so while adding to times is no
    problem reducing them could be undefined...

    Chris C
     
    Chris Croughton, Feb 12, 2005
    #9
  10. John Hanley

    Al Bowers Guest

    Chris Croughton wrote:

    > On Sat, 12 Feb 2005 10:00:16 -0700, John Hanley


    >
    >>What I have been doing is getting the calendar time from broken time,
    >>subtracting so many seconds from it (which is actually equivalent to 1 to 59
    >>minutes) and converting the calendar time back to broken time. The reason I
    >>do it this way is so that if it's Jan 1, 2000 at 00:00, subtracting 45
    >>minutes (45*60 seconds) from this gets me an entirely new date, not just a
    >>change in minutes.
    >>
    >>Is this approach ok, or will I run into any future undefined behaviour?

    >
    >
    > It will probably work until something changes. It is, however undefined
    > in the C standard (IIRC POSIX.1 defines it for systems which comply with
    > that standard).
    >
    > The correct way to manipulate times is to use the broken-down structure,
    > mess about with the fields and make that back into a time_t using
    > mktime(). For instance, to get the time 2:23:45 from now use:
    >
    > time_t now = time(NULL);
    > time_t then;
    > struct tm tt = *gmtime(&now);
    > tt.tm_hour += 2;;
    > tt.tm_min += 23;
    > tt.tm_sec += 45;
    > then = mktime(&tt);
    >
    > (that's a snippet, not a complete program -- some of the pedants will
    > complain about not including headers and the like if I don't say that).
    >
    > Unfortunately, the C standard doesn't say anything about the allowable
    > ranges of the fields, except that they are of type int and the normal
    > ranges are what you would expect. In particular, it doesn't say whether
    > negative values have the correct effect, so while adding to times is no
    > problem reducing them could be undefined...
    >


    No. What the Standard says is that function mktime will bring
    all values into range. For example the range for struct tm member
    tm_sec is 0-59. If tm_sec has the value of say -69 the function
    mktime will bring tm_sec into range by subtracting 1 from tm_min.
    And on up the ladder, if necessary, until finally tm_mon and
    tm_year are determined. Then tm_wday and tm_yday components of the
    struct are set appropriately. I would think that a Standard C
    that would allow you to add to a time but make reducing it undefined
    would be unwise.

    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
     
    Al Bowers, Feb 13, 2005
    #10
  11. On Sat, 12 Feb 2005 10:11:09 -0700, John Hanley wrote:

    >> I see what you mean. My problem is that I am actually trying to adjust
    >> minutes (from 1 to 59) and subtract the CHG_TIME number from the number of
    >> minutes. However, if my date is Jan 1, 2000 at 00:00, by changing the
    >> minutes, the hour, day, month, & year all have to change as well. That's
    >> why I thought if I could get the time_t value as calendar time, subtract
    >> from it number of minutes*60 (the correct number of seconds), and use
    >> mktime(), I would get the adjusted date (the date-CHG_TIME).

    >
    > sorry, that should read "and use gmtime(), I would get the adjusted date..."


    Normally you would use localtime(). Note that mktime() works from local
    time, not UTC.

    Lawrence
     
    Lawrence Kirby, Feb 17, 2005
    #11
  12. John Hanley

    John Hanley Guest

    "Al Bowers" <> wrote in message
    news:...
    >
    >
    > John Hanley wrote:
    > > I created a function that breaks down a date into broken down time, I
    > > subtract a certain number of seconds from that, then use mktime() to
    > > recompute the calendar time.
    > >
    > > It works basically except every so often, I get the date 060207 (Feb 7,
    > > 2006) which is obviously not correct. When it does this it always gives

    me
    > > this date.
    > >
    > > I tracked it down to my mktime() call, when I get to a certain date,

    mktime
    > > returns a number in 4000000000, when it should return a number in
    > > 1000000000. But I am not sure why. The variable in my tm struct all

    have
    > > the correct date, but mktime returns this.
    > >
    > > It is happening to me when the date I am changing is: 040727 but it has

    done
    > > this on others as well.
    > >
    > > I am thinking that something goes wrong in mktime() to cause it to

    return
    > > some default number. Perhaps something wrong in one of my time_broken
    > > members and then it gets past to mktime?
    > >
    > > Suggestions? Thanks a bunch!
    > >
    > > Here's my code:

    >
    > The code is not complete and it is not easy to follow the logic.
    > But I see you are making some errors. Apparently, you are
    > assuming that type time_t is type long representing seconds.
    > Standard C does not specify this to be fact. The Standard
    > only specifies that time_t be an arithmetic time capable of
    > representing time. And, it does not specify anything on
    > its instrumentality. So, to be portable, the code must not
    > assume the type to be type long and the values representing
    > seconds. To get around this, Standard C provides functions
    > that will allow you to manipulate time. So, to correct
    > your function adjust_time, you will need to convert the
    > time_t value to broken down time and the adjust the struct
    > member tm_sec in the number of seconds. Then call function
    > mktime to generate a new time_t value.


    Ok. So I tried this and after calling mktime, I then call gmtime to convert
    the (normalized) calendar time back into broken time. I need the broken
    time because I need the values of month, day, year, etc each separately. So
    I created a test program as follows. Here I am subtracting minutes (as my
    program needs to subtract 0-59 minutes from the date):

    eg:

    struct tm time_broken; /* time in broken time */
    time_t time_calendar=0; /* calendar time as a long int */

    /* create the struct tm */
    time_broken.tm_sec=0;
    time_broken.tm_min=0;
    time_broken.tm_hour=0;
    time_broken.tm_mday=1;
    time_broken.tm_mon=0;
    time_broken.tm_year=104; /* years since 1900 */
    time_broken.tm_isdst=-1;

    time_broken.tm_min=time_broken.tm_min-45;

    time_calendar=mktime(&time_broken);

    time_broken=*(gmtime(&time_calendar));

    printf("%s\n",asctime(&time_broken));

    and I get the correct date.

    Am I making any incorrect assumptions here? Will this work ok?

    Thanks a bunch for the help!

    John
     
    John Hanley, Feb 19, 2005
    #12
  13. John Hanley

    Al Bowers Guest

    John Hanley wrote:

    >
    > Ok. So I tried this and after calling mktime, I then call gmtime to convert
    > the (normalized) calendar time back into broken time. I need the broken
    > time because I need the values of month, day, year, etc each separately. So
    > I created a test program as follows. Here I am subtracting minutes (as my
    > program needs to subtract 0-59 minutes from the date):
    >
    > eg:
    >
    > struct tm time_broken; /* time in broken time */
    > time_t time_calendar=0; /* calendar time as a long int */
    >
    > /* create the struct tm */
    > time_broken.tm_sec=0;
    > time_broken.tm_min=0;
    > time_broken.tm_hour=0;
    > time_broken.tm_mday=1;
    > time_broken.tm_mon=0;
    > time_broken.tm_year=104; /* years since 1900 */
    > time_broken.tm_isdst=-1;
    >
    > time_broken.tm_min=time_broken.tm_min-45;
    >
    > time_calendar=mktime(&time_broken);
    >


    Just a reminder that the return value of mktime should
    be checked. The range of times on many implementations
    is limited. Therefore, it is not unusual for you to
    encounter the (time_t)-1 return value indicating time
    is not available for the arguments you supplied.

    > time_broken=*(gmtime(&time_calendar));
    >
    > printf("%s\n",asctime(&time_broken));
    >



    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
     
    Al Bowers, Feb 19, 2005
    #13
  14. On Sat, 12 Feb 2005 23:33:50 -0500, Al Bowers <>
    wrote:

    > Chris Croughton wrote:

    <snip>
    > > The correct way to [offset] times is to use the broken-down structure,
    > > mess about with the fields and make that back into a time_t using
    > > mktime(). For instance, to get the time 2:23:45 from now use:
    > >
    > > time_t now = time(NULL);
    > > time_t then;
    > > struct tm tt = *gmtime(&now);
    > > tt.tm_hour += 2;;
    > > tt.tm_min += 23;
    > > tt.tm_sec += 45;
    > > then = mktime(&tt);
    > >
    > > (that's a snippet, not a complete program -- some of the pedants will
    > > complain about not including headers and the like if I don't say that).
    > >
    > > Unfortunately, the C standard doesn't say anything about the allowable
    > > ranges of the fields, except that they are of type int and the normal
    > > ranges are what you would expect. In particular, it doesn't say whether
    > > negative values have the correct effect, so while adding to times is no
    > > problem reducing them could be undefined...
    > >

    >
    > No. What the Standard says is that function mktime will bring
    > all values into range. For example the range for struct tm member


    If the call is successful, yes. It (definitely) won't be if the
    requested time is not representable in time_t, and it's not clear if
    mktime() is allowed to fail in other cases that the implementor
    decides are "too hard" -- the comments in the Olson public-domain
    implementation imply to me that this might have happened.

    > tm_sec is 0-59. If tm_sec has the value of say -69 the function
    > mktime will bring tm_sec into range by subtracting 1 from tm_min.


    Actually tm_sec is 0-60 to allow for (positive) leap seconds, which
    are rarely if ever implemented. That is, leap seconds actually happen
    (for now, there has been discussion of eliminating them) but (most?) C
    implementations (and systems) just treat them as transient errors.
    The only people I've heard of actually using them are the ones for
    whom they were designed -- astronomers and space navigators, and their
    only contact to most ordinary people, GPS.

    Presumably you meant -60sec = -1min. -69sec = -2min leaving 51sec.

    > And on up the ladder, if necessary, until finally tm_mon and
    > tm_year are determined. Then tm_wday and tm_yday components of the
    > struct are set appropriately. I would think that a Standard C
    > that would allow you to add to a time but make reducing it undefined
    > would be unwise.


    - David.Thompson1 at worldnet.att.net
     
    Dave Thompson, Feb 21, 2005
    #14
  15. John Hanley

    infobahn Guest

    Dave Thompson wrote:
    >

    <snip>
    >
    > Actually tm_sec is 0-60 to allow for (positive) leap seconds, which
    > are rarely if ever implemented. That is, leap seconds actually happen
    > (for now, there has been discussion of eliminating them) but (most?) C
    > implementations (and systems) just treat them as transient errors.
    > The only people I've heard of actually using them are the ones for
    > whom they were designed -- astronomers and space navigators, and their
    > only contact to most ordinary people, GPS.


    Is it your claim that astronomers don't have telephones, or that
    they don't know how to use them?
     
    infobahn, Feb 21, 2005
    #15
  16. John Hanley

    Al Bowers Guest

    Dave Thompson wrote:

    >>>
    >>>

    >>No. What the Standard says is that function mktime will bring
    >>all values into range. For example the range for struct tm member
    >>
    >>

    >
    >If the call is successful, yes. It (definitely) won't be if the
    >requested time is not representable in time_t, and it's not clear if
    >mktime() is allowed to fail in other cases that the implementor
    >decides are "too hard" -- the comments in the Olson public-domain
    >implementation imply to me that this might have happened.
    >
    >
    >

    Yes, the Standard does not specify anthing on the resulting values of
    the struct tm
    members should and and when an implement of function mktime decides that
    time is
    not representable. The values may be changed or unchanged, in part or
    in total.

    >>tm_sec is 0-59. If tm_sec has the value of say -69 the function
    >>mktime will bring tm_sec into range by subtracting 1 from tm_min.
    >>
    >>

    >
    >Actually tm_sec is 0-60 to allow for (positive) leap seconds, which
    >are rarely if ever implemented. That is, leap seconds actually happen
    >(for now, there has been discussion of eliminating them) but (most?) C
    >implementations (and systems) just treat them as transient errors.
    >The only people I've heard of actually using them are the ones for
    >whom they were designed -- astronomers and space navigators, and their
    >only contact to most ordinary people, GPS.
    >
    >
    >

    I believe the Standard specifies the representable range as 0-59. I do
    not recall any mention
    of leap seconds in the Standard. Perhaps you are referring to an
    implement that extends
    the Standard. Unfortumately, I will be away from headquarters for a
    week, and not have
    access to the Standard document. Please correct me if I am wrong.

    >Presumably you meant -60sec = -1min. -69sec = -2min leaving 51sec.
    >
    >
    >

    Yes, the result to bring tm_sec into range would be a decrease of 2 in
    tm_min and an
    increase of 120 in tm_sec to bring it's value in range at 51 (120-69).

    >>And on up the ladder, if necessary, until finally tm_mon and
    >>tm_year are determined. Then tm_wday and tm_yday components of the
    >>struct are set appropriately. I would think that a Standard C
    >>that would allow you to add to a time but make reducing it undefined
    >>would be unwise.
    >>
    >>

    >
    >
    >


    Al Bowers
     
    Al Bowers, Feb 21, 2005
    #16
  17. John Hanley

    Michael Mair Guest

    Al Bowers wrote:
    > Dave Thompson wrote:
    >
    >>>>
    >>>
    >>> No. What the Standard says is that function mktime will bring
    >>> all values into range. For example the range for struct tm member
    >>>

    >>
    >>
    >> If the call is successful, yes. It (definitely) won't be if the
    >> requested time is not representable in time_t, and it's not clear if
    >> mktime() is allowed to fail in other cases that the implementor
    >> decides are "too hard" -- the comments in the Olson public-domain
    >> implementation imply to me that this might have happened.
    >>
    >>
    >>

    > Yes, the Standard does not specify anthing on the resulting values of
    > the struct tm
    > members should and and when an implement of function mktime decides that
    > time is
    > not representable. The values may be changed or unchanged, in part or
    > in total.
    >
    >>> tm_sec is 0-59. If tm_sec has the value of say -69 the function
    >>> mktime will bring tm_sec into range by subtracting 1 from tm_min.
    >>>

    >>
    >>
    >> Actually tm_sec is 0-60 to allow for (positive) leap seconds, which
    >> are rarely if ever implemented. That is, leap seconds actually happen
    >> (for now, there has been discussion of eliminating them) but (most?) C
    >> implementations (and systems) just treat them as transient errors.
    >> The only people I've heard of actually using them are the ones for
    >> whom they were designed -- astronomers and space navigators, and their
    >> only contact to most ordinary people, GPS.
    >>
    >>

    > I believe the Standard specifies the representable range as 0-59. I do
    > not recall any mention
    > of leap seconds in the Standard. Perhaps you are referring to an
    > implement that extends
    > the Standard. Unfortumately, I will be away from headquarters for a
    > week, and not have
    > access to the Standard document. Please correct me if I am wrong.


    Read it just this weekend in C Unleashed, so I am sure the range
    is 0..60; however we can have the look at the standard:

    "7.23.1 Components of time
    .....
    4 The range and precision of times representable in clock_t and time_t
    are implementation-defined. The tm structure shall contain at least the
    following members, in any order. The semantics of the members and their
    normal ranges are expressed in the comments.265)
    int tm_sec; // seconds after the minute [0, 60]
    int tm_min; // minutes after the hour [0, 59]
    int tm_hour; // hours since midnight [0, 23]
    int tm_mday; // day of the month [1, 31]
    int tm_mon; // months since January [0, 11]
    int tm_year; // years since 1900
    int tm_wday; // days since Sunday [0, 6]
    int tm_yday; // days since January 1 [0, 365]
    int tm_isdst; // Daylight Saving Time flag

    ________________________________________________________________________
    265) The range [0, 60] for tm_sec allows for a positive leap second.
    "

    Cheers
    Michael
    --
    E-Mail: Mine is a gmx dot de address.
     
    Michael Mair, Feb 21, 2005
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Florian Quetting

    mktime segfault

    Florian Quetting, Dec 31, 2004, in forum: C++
    Replies:
    2
    Views:
    534
    Florian Quetting
    Dec 31, 2004
  2. Rajmohan

    GMT equivalent of mktime

    Rajmohan, Jul 14, 2003, in forum: C Programming
    Replies:
    1
    Views:
    924
    Mark McIntyre
    Jul 14, 2003
  3. Gore

    mktime and DST.

    Gore, Oct 7, 2003, in forum: C Programming
    Replies:
    1
    Views:
    4,362
    Richard Bos
    Oct 7, 2003
  4. Bengt Richter

    time.mktime memory access violation bug

    Bengt Richter, Nov 18, 2003, in forum: Python
    Replies:
    6
    Views:
    746
    Bengt Richter
    Nov 21, 2003
  5. Victor Hooi
    Replies:
    8
    Views:
    197
    Barry Scott
    Jan 3, 2013
Loading...

Share This Page