Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A day without midnight

Tags:

timezone

There's at least one time zone that skips from 23:59:59 to 1:00:00 when "springing forward" for DST. Does anyone know what it is?

The following normally gets today's date, but it fails one day a year for time zones matching the above criterion.

$ perl -MDateTime -E'say DateTime->today( time_zone => $ARGV[0] )->ymd;' \
   America/New_York
2013-08-28

I need the time zone for testing purposes. I'm not trying to get the above code to work.

like image 897
ikegami Avatar asked Aug 28 '13 13:08

ikegami


2 Answers

I've thrown together a small program in Java to find all zones that contain a date in 2020 where the start of the date is not midnight. Its output lists all the time zones on my machine and version of Java matching your requirements as of 2020, as well as the date & time of the non-midnight start of day.

import java.time.*;
import java.time.zone.ZoneRulesProvider;
import java.util.stream.Stream;

public class ListTimeZonesWithoutMidnight {
    public static void main(String[] args) {
        System.out.printf("Java vendor & version: %s %s\n", System.getProperty("java.vendor"), Runtime.version());
        System.out.printf("Zone rules versions: %s\n", ZoneRulesProvider.getVersions("UTC").keySet());
        System.out.println();

        ZoneId.getAvailableZoneIds().stream().sorted().map(ZoneId::of)
                .flatMap(zoneId -> getNonMidnightStartOfDays(Year.of(2020), zoneId))
                .forEachOrdered(System.out::println);
    }

    private static Stream<LocalDate> getAllDates(Year year) {
        return year.atDay(1).datesUntil(year.plusYears(1).atDay(1));
    }

    private static Stream<ZonedDateTime> getNonMidnightStartOfDays(Year year, ZoneId zoneId) {
        return getAllDates(year).map(d -> d.atStartOfDay(zoneId))
                .filter(d -> !d.toLocalTime().equals(LocalTime.MIDNIGHT));
    }
}

Output:

Java vendor & version: AdoptOpenJDK 14.0.1+7
Zone rules versions: [2019c]

2020-10-04T01:00-03:00[America/Asuncion]
2020-03-08T01:00-04:00[America/Havana]
2020-09-06T01:00-03:00[America/Santiago]
2020-03-29T01:00Z[America/Scoresbysund]
2020-03-27T01:00+03:00[Asia/Amman]
2020-03-29T01:00+03:00[Asia/Beirut]
2020-03-27T01:00+03:00[Asia/Damascus]
2020-03-27T01:00+03:00[Asia/Gaza]
2020-03-27T01:00+03:00[Asia/Hebron]
2020-03-21T01:00+04:30[Asia/Tehran]
2020-03-29T01:00Z[Atlantic/Azores]
2020-09-06T01:00-03:00[Chile/Continental]
2020-03-08T01:00-04:00[Cuba]
2020-03-21T01:00+04:30[Iran]

Those 14 zone names are in 10 countries: Paraguay, Cuba, Chile, Greenland/Denmark, Jordan, Lebanon, Syria, Palestine, Iran, and Azores/Portugal.

like image 128
M. Justin Avatar answered Nov 20 '22 11:11

M. Justin


There are several. As of 2020-04, there are 14 such time zones in 10 countries: Paraguay, Cuba, Chile, Greenland/Denmark, Jordan, Lebanon, Syria, Palestine, Iran, and Azores/Portugal.

Before 2019-04, the list included Brazil using the America/Sao_Paulo time zone.

$ perl -MDateTime -E'say DateTime->new(
     year => 2013, month => 10, day => 20, hour => 12,
     time_zone => "America/Sao_Paulo")->truncate( to => "day" )->ymd;'
Invalid local time for date in time zone: America/Sao_Paulo

You can get around the problem by switching to the "floating" tome zone before getting the date:

$ perl -MDateTime -E'say DateTime->new(
     year => 2013, month => 10, day => 20, hour => 12,
     time_zone => "America/Sao_Paulo")
   ->set_time_zone("floating")
   ->truncate( to => "day" )
   ->ymd;'
2013-10-20

See this documentation.

like image 10
Matt Johnson-Pint Avatar answered Nov 20 '22 12:11

Matt Johnson-Pint