On Fri, Dec 27, 2013 at 1:48 PM, Zefram <zef...@fysh.org> wrote: > Eric Brine wrote: > >Given a date and time zone, is it possible to obtain the first time of > that > >date? > > Given standard APIs for time conversion, I'd perform a binary search > among UT times, converting them to the zone's local time and looking > for the threshold at which the local date changes. The result of the > conversion at the threshold time includes a local time-of-day that should > be the one you're after. >
I posted a solution here: http://stackoverflow.com/a/20850899/589924 I perform a binary search of the tz's spans, looking at the *local* times. If a span is found (i.e. if midnight does exist locally), I convert the local time to a UTC time using the offset of the earliest matching span. (The latest span is usually used.) If a span isn't found (i.e. if midnight does not exist locally), I use the UTC start time of the following span. *I made one assumption*: There is no dt to which one can add time to obtain a dt with an earlier date. Test: sub new_date { my $y = shift; my $m = shift; my $d = shift; return DateTime->new( year => $y, month => $m, day => $d, @_, hour => 0, minute => 0, second => 0, nanosecond => 0, time_zone => 'floating' );} { # No midnight. my $tz = DateTime::TimeZone->new( name => 'America/Sao_Paulo' ); my $dt = day_start($tz, new_date(2013, 10, 20)); print($dt->iso8601(), "\n"); # 2013-10-20T01:00:00 $dt->subtract( seconds => 1 ); print($dt->iso8601(), "\n"); # 2013-10-19T23:59:59} { # Two midnights. my $tz = DateTime::TimeZone->new( name => 'America/Havana' ); my $dt = day_start($tz, new_date(2013, 11, 3)); print($dt->iso8601(), "\n"); # 2013-11-03T00:00:00 $dt->subtract( seconds => 1 ); print($dt->iso8601(), "\n"); # 2013-11-02T23:59:59} I intend to write a brute force tester. Another type of edge case also might matter, depending on what you > mean by "the first time of that date". If you actually want the local > time-of-day at the beginning of the calendar day, that's fine. > The dt from which nothing can be subtracted to obtain a dt with the same date. > But if iyou actually want the lowest local time-of-day that occurs at any > time > during the calendar day, you could in principle be misled by a zone that > jumps forward at midnight and then back slightly later (say, forward an > hour at local 00:00->01:00, then back an hour at local 01:30->00:30). > I think this also doesn't occur anywhere in the database. > I'd want the first 01:00, and my solution would get it. - Eric