using mktime()

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Hanley

    #1

    using mktime()

    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,md ay,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%1000 0)/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=m ktime(&time_bro ken);

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

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

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

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

    return 0;
    }


  • Mike Wahler

    #2
    Re: using mktime()


    "John Hanley" <hanley@ualbert a.ca> wrote in message
    news:1108176063 .411336@proxy2. srv.ualberta.ca ...[color=blue]
    > 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[/color]
    me[color=blue]
    > this date.
    >
    > I tracked it down to my mktime() call, when I get to a certain date,[/color]
    mktime[color=blue]
    > 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[/color]
    done[color=blue]
    > 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:[/color]

    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



    Comment

    • j

      #3
      Re: using mktime()


      "John Hanley" <hanley@ualbert a.ca> wrote in message
      news:1108176063 .411336@proxy2. srv.ualberta.ca ...[color=blue]
      > 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[/color]
      me[color=blue]
      > this date.
      >
      > I tracked it down to my mktime() call, when I get to a certain date,[/color]
      mktime[color=blue]
      > 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[/color]
      done[color=blue]
      > 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,md ay,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%1000 0)/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=m ktime(&time_bro ken);[/color]

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



      --
      j


      Comment

      • Al Bowers

        #4
        Re: using mktime()



        John Hanley wrote:[color=blue]
        > 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:[/color]

        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(&tval ue);
        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: xabowers@myrapi dsys.com (remove the x to send email)
        Latest news coverage, email, free stock quotes, live scores and video are just the beginning. Discover more every day at Yahoo!


        Comment

        • John Hanley

          #5
          Re: using mktime()

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

          you're right, that was what I was assuming.
          [color=blue]
          > 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.[/color]

          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

          [color=blue]
          >
          >
          > 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(&tval ue);
          > 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: xabowers@myrapi dsys.com (remove the x to send email)
          > http://www.geocities.com/abowers822/
          >[/color]


          Comment

          • John Hanley

            #6
            Re: using mktime()


            "j" <jake30NOSPAM@b ellsouth.net> wrote in message
            news:RUhPd.889$ u16.523@bignews 6.bellsouth.net ...[color=blue]
            >
            > "John Hanley" <hanley@ualbert a.ca> wrote in message
            > news:1108176063 .411336@proxy2. srv.ualberta.ca ...[color=green]
            > > 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[/color]
            > me[color=green]
            > > this date.
            > >
            > > I tracked it down to my mktime() call, when I get to a certain date,[/color]
            > mktime[color=green]
            > > 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[/color][/color]
            have[color=blue][color=green]
            > > the correct date, but mktime returns this.
            > >
            > > It is happening to me when the date I am changing is: 040727 but it has[/color]
            > done[color=green]
            > > this on others as well.
            > >
            > > I am thinking that something goes wrong in mktime() to cause it to[/color][/color]
            return[color=blue][color=green]
            > > 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,md ay,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%1000 0)/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=m ktime(&time_bro ken);[/color]
            >
            > You never assign a meaningful value to member ``tm_isdst''.
            > mktime thus uses an indeterminate value and the consequence
            > is undefined behaviour.[/color]

            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


            Comment

            • John Hanley

              #7
              Re: using mktime()

              > I see what you mean. My problem is that I am actually trying to adjust[color=blue]
              > 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).[/color]

              sorry, that should read "and use gmtime(), I would get the adjusted date..."
              [color=blue]
              >
              > 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.[/color]

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

              sorry for the confusion.
              [color=blue]
              >
              > 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[/color]
              having[color=blue]
              > to do it manually?
              >
              > Thanks so much for the help! I really appreciate it!
              >
              > John
              >
              >[color=green]
              > >
              > >
              > > 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(&tval ue);
              > > 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: xabowers@myrapi dsys.com (remove the x to send email)
              > > http://www.geocities.com/abowers822/
              > >[/color]
              >
              >[/color]


              Comment

              • Al Bowers

                #8
                Re: using mktime()



                John Hanley wrote:
                [color=blue][color=green]
                >>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.[/color]
                >
                >
                > you're right, that was what I was assuming.
                >
                >[color=green]
                >>Standard C does not specify this to be fact. The Standard
                >>only specifies that time_t be an arithmetic time capable of
                >>representin g 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.[/color]
                >
                >
                > 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.
                >[/color]

                You should not make this assumption if you are writing portable Standard
                C code.
                [color=blue]
                > 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?
                >[/color]
                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;
                }



                [color=blue]
                > Thanks so much for the help! I really appreciate it!
                >
                > John
                >
                >
                >[color=green]
                >>
                >>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(&tval ue);
                >> 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: xabowers@myrapi dsys.com (remove the x to send email)
                >>http://www.geocities.com/abowers822/
                >>[/color]
                >
                >
                >[/color]

                --
                Al Bowers
                Tampa, Fl USA
                mailto: xabowers@myrapi dsys.com (remove the x to send email)
                Latest news coverage, email, free stock quotes, live scores and video are just the beginning. Discover more every day at Yahoo!


                Comment

                • Chris Croughton

                  #9
                  Re: using mktime()

                  On Sat, 12 Feb 2005 10:00:16 -0700, John Hanley
                  <hanley@ualbert a.ca> wrote:
                  [color=blue]
                  > 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.[/color]

                  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).
                  [color=blue]
                  > 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.[/color]

                  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.
                  [color=blue]
                  > 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?[/color]

                  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

                  Comment

                  • Al Bowers

                    #10
                    Re: using mktime()



                    Chris Croughton wrote:
                    [color=blue]
                    > On Sat, 12 Feb 2005 10:00:16 -0700, John Hanley[/color]
                    [color=blue]
                    >[color=green]
                    >>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?[/color]
                    >
                    >
                    > 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...
                    >[/color]

                    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: xabowers@myrapi dsys.com (remove the x to send email)
                    Latest news coverage, email, free stock quotes, live scores and video are just the beginning. Discover more every day at Yahoo!


                    Comment

                    • Lawrence Kirby

                      #11
                      Re: using mktime()

                      On Sat, 12 Feb 2005 10:11:09 -0700, John Hanley wrote:
                      [color=blue][color=green]
                      >> 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).[/color]
                      >
                      > sorry, that should read "and use gmtime(), I would get the adjusted date..."[/color]

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

                      Lawrence

                      Comment

                      • John Hanley

                        #12
                        Re: using mktime()


                        "Al Bowers" <xabowers@rapid sys.com> wrote in message
                        news:376hifF58n 6jrU1@individua l.net...[color=blue]
                        >
                        >
                        > John Hanley wrote:[color=green]
                        > > 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[/color][/color]
                        me[color=blue][color=green]
                        > > this date.
                        > >
                        > > I tracked it down to my mktime() call, when I get to a certain date,[/color][/color]
                        mktime[color=blue][color=green]
                        > > 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[/color][/color]
                        have[color=blue][color=green]
                        > > the correct date, but mktime returns this.
                        > >
                        > > It is happening to me when the date I am changing is: 040727 but it has[/color][/color]
                        done[color=blue][color=green]
                        > > this on others as well.
                        > >
                        > > I am thinking that something goes wrong in mktime() to cause it to[/color][/color]
                        return[color=blue][color=green]
                        > > 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:[/color]
                        >
                        > 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.[/color]

                        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=m ktime(&time_bro ken);

                        time_broken=*(g mtime(&time_cal endar));

                        printf("%s\n",a sctime(&time_br oken));

                        and I get the correct date.

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

                        Thanks a bunch for the help!

                        John


                        Comment

                        • Al Bowers

                          #13
                          Re: using mktime()



                          John Hanley wrote:
                          [color=blue]
                          >
                          > 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=m ktime(&time_bro ken);
                          >[/color]

                          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.
                          [color=blue]
                          > time_broken=*(g mtime(&time_cal endar));
                          >
                          > printf("%s\n",a sctime(&time_br oken));
                          >[/color]


                          --
                          Al Bowers
                          Tampa, Fl USA
                          mailto: xabowers@myrapi dsys.com (remove the x to send email)
                          Latest news coverage, email, free stock quotes, live scores and video are just the beginning. Discover more every day at Yahoo!


                          Comment

                          • Dave Thompson

                            #14
                            Re: using mktime()

                            On Sat, 12 Feb 2005 23:33:50 -0500, Al Bowers <xabowers@rapid sys.com>
                            wrote:
                            [color=blue]
                            > Chris Croughton wrote:[/color]
                            <snip>[color=blue][color=green]
                            > > 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...
                            > >[/color]
                            >
                            > No. What the Standard says is that function mktime will bring
                            > all values into range. For example the range for struct tm member[/color]

                            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.
                            [color=blue]
                            > 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.[/color]

                            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.
                            [color=blue]
                            > 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.[/color]

                            - David.Thompson1 at worldnet.att.ne t

                            Comment

                            • infobahn

                              #15
                              Re: using mktime()

                              Dave Thompson wrote:[color=blue]
                              >[/color]
                              <snip>[color=blue]
                              >
                              > 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.[/color]

                              Is it your claim that astronomers don't have telephones, or that
                              they don't know how to use them?

                              Comment

                              Working...