Re: Bug #630: date/time storage problem: timestamp parsed - Mailing list pgsql-bugs

From Sean Chittenden
Subject Re: Bug #630: date/time storage problem: timestamp parsed
Date
Msg-id 20020409214442.T66679@ninja1.internal
Whole thread Raw
In response to Re: Bug #630: date/time storage problem: timestamp parsed  (Thomas Lockhart <lockhart@fourpalms.org>)
Responses Re: Bug #630: date/time storage problem: timestamp parsed
List pgsql-bugs
> > Looks like it's a "bug" in mktime() on FreeBSD: it doesn't seem to
> > do so well with invalid times that happen between daylight savings
> > time...  or is that a postgres thing for not kicking up an error
> > (out of bounds time)?  Or should 2am PST be converted to 3am?  -sc
>
> Here is the man page on Linux:
>
> The mktime() function converts a broken-down time structure,
> expressed as local time, to calendar time representation. The
> function ignores the specified contents of the structure members
> tm_wday and tm_yday and recomputes them from the other information
> in the broken-down time structure. If structure members are outside
> their legal interval, they will be normalized (so that, e.g., 40
> October is changed into 9 November). Calling mktime() also sets the
> external variable tzname with information about the current time
> zone. If the specified broken-down time cannot be represented as
> calendar time (seconds since the epoch), mktime() returns a value of
> (time_t)(-1) and does not alter the tm_wday and tm_yday members of
> the broken-down time structure.
>
>
> Does that look similar to FreeBSD?

Very familiar, from mktime(2):

     The functions mktime() and timegm() convert the broken-down time
     in the structure pointed to by tm into a time value with the same
     encoding as that of the values returned by the time(3) function
     (that is, seconds from the Epoch, UTC).  mktime() interprets the
     input structure according to the current timezone setting (see
     tzset(3)).  timegm() interprets the input structure as
     representing Universal Coordinated Time (UTC).

     The original values of the tm_wday and tm_yday components of the
     struc- ture are ignored, and the original values of the other
     components are not restricted to their normal ranges, and will be
     normalized if needed.  For example, October 40 is changed into
     November 9, a tm_hour of -1 means 1 hour before midnight, tm_mday
     of 0 means the day preceding the current month, and tm_mon of -2
     means 2 months before January of tm_year.  (A positive or zero
     value for tm_isdst causes mktime() to presume initially that
     summer time (for example, Daylight Saving Time) is or is not in
     effect for the specified time, respectively.  A negative value
     for tm_isdst causes the mktime() function to attempt to divine
     whether summer time is in effect for the specified time.  The
     tm_isdst and tm_gmtoff members are forced to zero by timegm().)

> I don't think that our code checks explicitly for a "-1" return,
> since the range is checked just before the call, but it would
> probably be a good idea if it did (assuming that other mktime()
> implementations had the same convention for an error return of
> course).

Just poked through how Ruby handles this and it looks like they go to
reasonable lengths to make sure that it "does the right thing."

http://www.ruby-lang.org/~knu/cgi-bin/cvsweb.cgi/ruby/time.c?rev=1.55&content-type=text/x-cvsweb-markup

irb(main):005:0> Time.local(2002,4,7,1)
Sun Apr 07 01:00:00 PST 2002
irb(main):006:0> Time.local(2002,4,7,3)
Sun Apr 07 03:00:00 PDT 2002
irb(main):007:0> Time.local(2002,4,7,2)
Sun Apr 07 03:00:00 PDT 2002
irb(main):008:0> Time.local(2002,4,7,2,20)
Sun Apr 07 03:20:00 PDT 2002

It's artistically licensed...  ::shrug:: Time.local is a thin wrapper
around mktime().  Check out make_time_t() in the link above.

> This is the first report I can remember in 6 years of this
> particular symptom, and I have the strong feeling that no matter
> what we end up doing there *is* a problem with the FreeBSD database
> of time zones or (possibly) in its implementation of mktime().

I hope so...  this bug hit me nasty like.  I was doing a time series
regression and thought it'd be a cute exercise to sum up the
components...  when I hit only ~99.7% and found out that part of my
data was in 2036 I... flipped, freaked out, debugged, cursed,
scratched head, cursed more... then I went for a Guinness and my world
was calm again.  :~)

> What do you see as the return value from mktime()?

Ehh... let me hack/check.  Looks like 11.  ??  In
lib/libc/stdtime/localtime.c, WRONG is defined as -1, not 11.

1490                    t = mktime(tmp);
(gdb)
1491                    fprintf(stderr, "%p\n", t);  /* GCC optimizes this
                                                        away if I don't do
                            something */
(gdb)
0x3c5e5ba0
(gdb) print t
$1 = 11

Doesn't make much sense to me where that'd come from...  ? -sc

--
Sean Chittenden

pgsql-bugs by date:

Previous
From: Tom Lane
Date:
Subject: Re: Bug #630: date/time storage problem: timestamp parsed
Next
From: Tom Lane
Date:
Subject: Re: Bug #630: date/time storage problem: timestamp parsed