From d3b032a88df96813749a8b588d5874344eedb018 Mon Sep 17 00:00:00 2001 From: Packit Date: Sep 29 2020 14:01:04 +0000 Subject: perl-Net-CalDAVTalk-0.12 base --- diff --git a/Changes b/Changes new file mode 100644 index 0000000..68d15aa --- /dev/null +++ b/Changes @@ -0,0 +1,44 @@ +Revision history for Net-CalDAVTalk + +0.12 Wed Nov 15 14:44 2017 + - fix missing POD coverage + - add canSync response to GetCalendars + +0.11 Sun Nov 12 18:55 2017 + - add GetEventLinks, GetEventsMulti and SyncEventLinks APIs + - $Net::CalDAVTalk::BATCHSIZE = 100 default for GetEventsMulti + +0.10 Wed Feb 15 16:46 2017 + - set the timezone on recurrences based on the top level timezone, not + the recurrence timezone + +0.09 Fri Oct 14 11:49 2016 + - fix freebusy parsing for zero length events and updated stamp + - add JMAP_ALWAYS_FULL environment variable to suppress deep + diff creation + +0.08 Fri Oct 14 09:20 2016 + - major rewrite to support the new TC-API from CalConnect which + will be part of the JMAP specification, including tests + +0.07 Tue Jun 28 11:48 2016 + - uploaded bogus path, so just fix it with a new version + +0.06 Fri May 27 13:58 2016 + - don't bail on incomplete ACL information + +0.05 Mon May 2 11:27 2016 + - add UpdateAddressSet API + +0.04 Tue Mar 1 08:37 2016 + - require MIME::Types + - Add support for 'timezone' property + +0.03 Mon Aug 17 10:08 2015 + - Pull all documentation in, including doc for the TimeZones module + +0.02 Mon Aug 17 09:30 2015 + - Initial release with POD coverage, but missing some commits + +0.01 never released + diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..b3a759e --- /dev/null +++ b/MANIFEST @@ -0,0 +1,12 @@ +Changes +lib/Net/CalDAVTalk.pm +lib/Net/CalDAVTalk/TimeZones.pm +Makefile.PL +MANIFEST This list of files +README +t/00-load.t +t/manifest.t +t/pod-coverage.t +t/pod.t +META.yml Module YAML meta-data (added by MakeMaker) +META.json Module JSON meta-data (added by MakeMaker) diff --git a/META.json b/META.json new file mode 100644 index 0000000..a2bd73f --- /dev/null +++ b/META.json @@ -0,0 +1,52 @@ +{ + "abstract" : "Module to talk CalDAV and give a JSON interface to the data", + "author" : [ + "Bron Gondwana " + ], + "dynamic_config" : 1, + "generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010", + "license" : [ + "unknown" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Net-CalDAVTalk", + "no_index" : { + "directory" : [ + "t", + "inc" + ] + }, + "prereqs" : { + "build" : { + "requires" : { + "Test::More" : "0" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "runtime" : { + "requires" : { + "Data::ICal::TimeZone" : "1.23", + "DateTime::Format::ICal" : "0.09", + "DateTime::Format::ISO8601" : "0.08", + "DateTime::TimeZone" : "0", + "JSON" : "0", + "JSON::XS" : "0", + "MIME::Types" : "0", + "Net::DAVTalk" : "0.02", + "Text::LevenshteinXS" : "0.03", + "Text::VCardFast" : "0.06", + "perl" : "5.006" + } + } + }, + "release_status" : "stable", + "version" : "0.12", + "x_serialization_backend" : "JSON::PP version 2.27400_02" +} diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..1e6b5ad --- /dev/null +++ b/META.yml @@ -0,0 +1,33 @@ +--- +abstract: 'Module to talk CalDAV and give a JSON interface to the data' +author: + - 'Bron Gondwana ' +build_requires: + Test::More: '0' +configure_requires: + ExtUtils::MakeMaker: '0' +dynamic_config: 1 +generated_by: 'ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010' +license: unknown +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: '1.4' +name: Net-CalDAVTalk +no_index: + directory: + - t + - inc +requires: + Data::ICal::TimeZone: '1.23' + DateTime::Format::ICal: '0.09' + DateTime::Format::ISO8601: '0.08' + DateTime::TimeZone: '0' + JSON: '0' + JSON::XS: '0' + MIME::Types: '0' + Net::DAVTalk: '0.02' + Text::LevenshteinXS: '0.03' + Text::VCardFast: '0.06' + perl: '5.006' +version: '0.12' +x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..911e287 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,34 @@ +use 5.006; +use strict; +use warnings FATAL => 'all'; +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'Net::CalDAVTalk', + AUTHOR => q{Bron Gondwana }, + VERSION_FROM => 'lib/Net/CalDAVTalk.pm', + ABSTRACT_FROM => 'lib/Net/CalDAVTalk.pm', + LICENSE => 'Artistic_2_0', + PL_FILES => {}, + MIN_PERL_VERSION => 5.006, + CONFIGURE_REQUIRES => { + 'ExtUtils::MakeMaker' => 0, + }, + BUILD_REQUIRES => { + 'Test::More' => 0, + }, + PREREQ_PM => { + 'Net::DAVTalk' => '0.02', + 'DateTime::TimeZone' => 0, + 'Data::ICal::TimeZone' => '1.23', + 'DateTime::Format::ISO8601' => '0.08', + 'DateTime::Format::ICal' => '0.09', + 'Text::LevenshteinXS' => '0.03', + 'Text::VCardFast' => '0.06', + 'JSON' => 0, + 'JSON::XS' => 0, + 'MIME::Types' => 0, + }, + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, + clean => { FILES => 'Net-CalDAVTalk-*' }, +); diff --git a/README b/README new file mode 100644 index 0000000..c52a1b8 --- /dev/null +++ b/README @@ -0,0 +1,85 @@ +Net-CalDAVTalk + +The README is used to introduce the module and provide instructions on +how to install the module, any machine dependencies it may have (for +example C compilers and installed libraries) and any other information +that should be provided before the module is installed. + +A README file is required for CPAN modules since CPAN extracts the README +file from a module distribution so that people browsing the archive +can use it to get an idea of the module's uses. It is usually a good idea +to provide version information here so that people can decide whether +fixes for the module are worth downloading. + + +INSTALLATION + +To install this module, run the following commands: + + perl Makefile.PL + make + make test + make install + +SUPPORT AND DOCUMENTATION + +After installing, you can find documentation for this module with the +perldoc command. + + perldoc Net::CalDAVTalk + +You can also look for information at: + + RT, CPAN's request tracker (report bugs here) + http://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-CalDAVTalk + + AnnoCPAN, Annotated CPAN documentation + http://annocpan.org/dist/Net-CalDAVTalk + + CPAN Ratings + http://cpanratings.perl.org/d/Net-CalDAVTalk + + Search CPAN + http://search.cpan.org/dist/Net-CalDAVTalk/ + + +LICENSE AND COPYRIGHT + +Copyright (C) 2015 Bron Gondwana + +This program is free software; you can redistribute it and/or modify it +under the terms of the the Artistic License (2.0). You may obtain a +copy of the full license at: + +L + +Any use, modification, and distribution of the Standard or Modified +Versions is governed by this Artistic License. By using, modifying or +distributing the Package, you accept this license. Do not use, modify, +or distribute the Package, if you do not accept this license. + +If your Modified Version has been derived from a Modified Version made +by someone other than you, you are nevertheless required to ensure that +your Modified Version complies with the requirements of this license. + +This license does not grant you the right to use any trademark, service +mark, tradename, or logo of the Copyright Holder. + +This license includes the non-exclusive, worldwide, free-of-charge +patent license to make, have made, use, offer to sell, sell, import and +otherwise transfer the Package with respect to any patent claims +licensable by the Copyright Holder that are necessarily infringed by the +Package. If you institute patent litigation (including a cross-claim or +counterclaim) against any party alleging that the Package constitutes +direct or contributory patent infringement, then this Artistic License +to you shall terminate on the date that such litigation is filed. + +Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER +AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. +THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY +YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR +CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR +CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/lib/Net/CalDAVTalk.pm b/lib/Net/CalDAVTalk.pm new file mode 100644 index 0000000..2b42202 --- /dev/null +++ b/lib/Net/CalDAVTalk.pm @@ -0,0 +1,3222 @@ +package Net::CalDAVTalk; + +use 5.006; +use strict; +use warnings FATAL => 'all'; + +use Net::DAVTalk; +use base qw(Net::DAVTalk); + +use Carp; +use Data::ICal; +use Data::ICal::Entry::Event; +use Data::ICal::TimeZone; +use Data::ICal::Entry::Alarm::Email; +use Data::ICal::Entry::Alarm::Display; +use DateTime::Format::ICal; +use DateTime::TimeZone; +use JSON::XS qw(encode_json); +use Net::CalDAVTalk::TimeZones; +use Text::VCardFast qw(vcard2hash); +use XML::Spice; +use MIME::Base64 qw(encode_base64); +use MIME::Types; +use Digest::SHA qw(sha1_hex); +use URI::Escape qw(uri_unescape); + +our $BATCHSIZE = 100; + +# monkey patch like a bandit +BEGIN { + my @properties = Data::ICal::Entry::Alarm::optional_unique_properties(); + foreach my $want (qw(uid acknowledged)) { + push @properties, $want unless grep { $_ eq $want } @properties; + } + no warnings 'redefine'; + *Data::ICal::Entry::Alarm::optional_unique_properties = sub { @properties }; +} + +our ( + $DefaultCalendarColour, + $DefaultDisplayName, +); + +our $UTC = DateTime::TimeZone::UTC->new(); +our $FLOATING = DateTime::TimeZone::Floating->new(); +our $LOCALE = DateTime::Locale->load('en_US'); + +# Beginning and End of time as used for "all event" date ranges +# Reducing this range may result in events disappearing from FastMail +# calendars, as we think they have been deleted from the other end, +# so best to avoid this. +# However, from my tests, the events should be resurrected once this date +# window includes them again. + +my $BoT = '1970-01-01T00:00:00'; +my $EoT = '2038-01-19T00:00:00'; + +my ( + %WeekDayNames, + %WeekDayNamesReverse, + %DaysByName, + %DaysByIndex, + %ColourNames, + @Frequencies, + %RecurrenceProperties, + %UTCLinks, + %MustBeTopLevel, + %EventKeys, +); + +BEGIN { + %WeekDayNames = ( + su => 'sunday', + mo => 'monday', + tu => 'tuesday', + we => 'wednesday', + th => 'thursday', + fr => 'friday', + sa => 'saturday', + ); + %WeekDayNamesReverse = reverse %WeekDayNames; + + %DaysByName = ( + su => 0, + mo => 1, + tu => 2, + we => 3, + th => 4, + fr => 5, + sa => 6, + ); + + %DaysByIndex = reverse %DaysByName; + $DefaultCalendarColour = '#0252D4'; + $DefaultDisplayName = 'Untitled Calendar'; + @Frequencies = qw{yearly monthly weekly daily hourly minutely secondly}; + + %EventKeys = ( + '' => { + uid => [0, 'string', 1, undef], + relatedTo => [0, 'string', 0, undef], + prodId => [0, 'string', 0, undef], + created => [0, 'utcdate', 0, undef], + updated => [0, 'utcdate', 1, undef], + sequence => [0, 'number', 0, undef], + title => [0, 'string', 0, ''], + description => [0, 'string', 0, ''], + links => [0, 'object', 0, undef], + locale => [0, 'string', 0, undef], + localizations => [0, 'patch', 0, undef], + locations => [0, 'object', 0, undef], + isAllDay => [0, 'bool', 0, $JSON::false], + start => [0, 'localdate', 1, undef], + timeZone => [0, 'timezone', 0, undef], + duration => [0, 'duration', 0, undef], + recurrenceRule => [0, 'object', 0, undef], + recurrenceOverrides => [0, 'patch', 0, undef], + status => [0, 'string', 0, undef], + showAsFree => [0, 'bool', 0, undef], + replyTo => [0, 'object', 0, undef], + participants => [0, 'object', 0, undef], + useDefaultAlerts => [0, 'bool', 0, $JSON::false], + alerts => [0, 'object', 0, undef], + }, + replyTo => { + imip => [0, 'mailto', 0, undef], + web => [0, 'href', 0, undef], + }, + links => { + href => [0, 'string', 1, undef], + type => [0, 'string', 0, undef], + size => [0, 'number', 0, undef], + rel => [0, 'string', 1, undef], + title => [0, 'string', 1, undef], + properties => [0, 'string', 1, undef], + }, + locations => { + name => [0, 'string', 0, undef], + accessInstructions => [0, 'string', 0, undef], + rel => [0, 'string', 0, 'unknown'], + timeZone => [0, 'timezone', 0, undef], + address => [0, 'object', 0, undef], + coordinates => [0, 'string', 0, undef], + uri => [0, 'string', 0, undef], + }, + recurrenceRule => { + frequency => [0, 'string', 1, undef], + interval => [0, 'number', 0, undef], + rscale => [0, 'string', 0, 'gregorian'], + skip => [0, 'string', 0, 'omit'], + firstDayOfWeek => [0, 'string', 0, 'monday'], + byDay => [1, 'object', 0, undef], + byDate => [1, 'number', 0, undef], + byMonth => [1, 'string', 0, undef], + byYearDay => [1, 'number', 0, undef], + byWeekNo => [1, 'number', 0, undef], + byHour => [1, 'number', 0, undef], + byMinute => [1, 'number', 0, undef], + bySecond => [1, 'number', 0, undef], + bySetPosition => [1, 'number', 0, undef], + count => [0, 'number', 0, undef], + until => [0, 'localdate', 0, undef], + }, + byDay => { + day => [0, 'string', 1, undef], + nthOfPeriod => [0, 'number', 0, undef], + }, + participants => { + name => [0, 'string', 1, undef], + email => [0, 'string', 1, undef], + kind => [0, 'string', 0, 'unknown'], + roles => [1, 'string', 1, undef], + locationId => [0, 'string', 0, undef], + scheduleStatus => [0, 'string', 0, 'needs-action'], + schedulePriority => [0, 'string', 0, 'required'], + scheduleRSVP => [0, 'bool', 0, $JSON::false], + scheduleUpdated => [0, 'utcdate', 0, undef], + memberOf => [1, 'string', 0, undef], + }, + alerts => { + relativeTo => [0, 'string', 0, 'before-start'], + offset => [0, 'duration', 1, undef], + action => [0, 'object', 1, undef], + }, + action => { + type => [0, 'string', 1, undef], + }, + ); + + %RecurrenceProperties = ( + bymonthday => { + name => 'byDate', + max => 31, + signed => 1, + }, + byyearday => { + name => 'byYearDay', + max => 366, + signed => 1, + }, + byweekno => { + name => 'byWeekNo', + max => 53, + signed => 1, + }, + byhour => { + name => 'byHour', + max => 23, + }, + byminute => { + name => 'byMinute', + max => 59, + }, + bysecond => { + name => 'bySecond', + max => 60, + }, + bysetpos => { + name => 'bySetPosition', + max => 366, + signed => 1, + }, + ); + + %MustBeTopLevel = map { $_ => 1 } qw{ + uid + relatedTo + prodId + isAllDay + recurrenceRule + recurrenceOverrides + replyTo + participantId + }; + # not in tc-api / JMAP, but necessary for iMIP + $MustBeTopLevel{method} = 1; + + # Colour names defined in CSS Color Module Level 3 + # http://www.w3.org/TR/css3-color/ + + %ColourNames + = map { $_ => 1 } + qw{ + aliceblue + antiquewhite + aqua + aquamarine + azure + beige + bisque + black + blanchedalmond + blue + blueviolet + brown + burlywood + cadetblue + chartreuse + chocolate + coral + cornflowerblue + cornsilk + crimson + cyan + darkblue + darkcyan + darkgoldenrod + darkgray + darkgreen + darkgrey + darkkhaki + darkmagenta + darkolivegreen + darkorange + darkorchid + darkred + darksalmon + darkseagreen + darkslateblue + darkslategray + darkslategrey + darkturquoise + darkviolet + deeppink + deepskyblue + dimgray + dimgrey + dodgerblue + firebrick + floralwhite + forestgreen + fuchsia + gainsboro + ghostwhite + gold + goldenrod + gray + green + greenyellow + grey + honeydew + hotpink + indianred + indigo + ivory + khaki + lavender + lavenderblush + lawngreen + lemonchiffon + lightblue + lightcoral + lightcyan + lightgoldenrodyellow + lightgray + lightgreen + lightgrey + lightpink + lightsalmon + lightseagreen + lightskyblue + lightslategray + lightslategrey + lightsteelblue + lightyellow + lime + limegreen + linen + magenta + maroon + mediumaquamarine + mediumblue + mediumorchid + mediumpurple + mediumseagreen + mediumslateblue + mediumspringgreen + mediumturquoise + mediumvioletred + midnightblue + mintcream + mistyrose + moccasin + navajowhite + navy + oldlace + olive + olivedrab + orange + orangered + orchid + palegoldenrod + palegreen + paleturquoise + palevioletred + papayawhip + peachpuff + peru + pink + plum + powderblue + purple + red + rosybrown + royalblue + saddlebrown + salmon + sandybrown + seagreen + seashell + sienna + silver + skyblue + slateblue + slategray + slategrey + snow + springgreen + steelblue + tan + teal + thistle + tomato + turquoise + violet + wheat + white + whitesmoke + yellow + yellowgreen + }; + + %UTCLinks = ( + 'Etc/GMT-0' => 1, + 'Etc/GMT+0' => 1, + 'Etc/GMT0' => 1, + 'Etc/GMT' => 1, + 'Etc/Greenwich' => 1, + 'Etc/UCT' => 1, + 'Etc/Universal' => 1, + 'Etc/UTC' => 1, + 'Etc/Zulu' => 1, + 'GMT' => 1, + 'UCT' => 1, + 'UTC' => 1, + ); +} + + +=head1 NAME + +Net::CalDAVTalk - Module to talk CalDAV and give a JSON interface to the data + +=head1 VERSION + +Version 0.12 + +=cut + +our $VERSION = '0.12'; + + +=head1 SYNOPSIS + +This module is the initial release of the code used at FastMail for talking +to CalDAV servers. It's quite specific to an early version of our API, so +while it might be useful to others, it's being pushed to CPAN more because +the Cassandane test suite needs it. + +See Net::DAVTalk for details on how to specify hosts and paths. + + my $CalDAV = Net::CalDAVTalk->new( + user => $service->user(), + password => $service->pass(), + host => $service->host(), + port => $service->port(), + scheme => 'http', + url => '/', + expandurl => 1, + ); + +or using DNS: + + my $domain = $user; + $domain =~ s/.*\@//; + + my $url; + my ($reply) = $Resolver->search("_caldavs._tcp.$domain", "srv"); + if ($reply) { + my @d = $reply->answer; + if (@d) { + my $host = $d[0]->target(); + my $port = $d[0]->port(); + $url = "https://$host"; + $url .= ":$port" unless $port eq 443; + } + } + +This will use the '/.well-known/caldav' address to find the actual current user +principal, and from there the calendar-home-set for further operations. + + my $foo = Net::CalDAVTalk->new( + user => $user, + password => $password, + url => $url, + expandurl => 1, + ); + + +=head1 SUBROUTINES/METHODS + +=head2 new(%args) + +Takes the same arguments as Net::DAVTalk and adds the caldav namespaces +and some Cyrus specific namespaces for all XML requests. + + A => 'http://apple.com/ns/ical/' + C => 'urn:ietf:params:xml:ns:caldav' + CY => 'http://cyrusimap.org/ns/' + UF => 'http://cyrusimap.org/ns/userflag/' + SF => 'http://cyrusimap.org/ns/sysflag/' + +=cut + +sub new { + my ($Class, %Params) = @_; + + $Params{homesetns} = 'C'; + $Params{homeset} = 'calendar-home-set'; + $Params{wellknown} = 'caldav'; + + my $Self = $Class->SUPER::new(%Params); + + $Self->ns(A => 'http://apple.com/ns/ical/'); + $Self->ns(C => 'urn:ietf:params:xml:ns:caldav'); + $Self->ns(CY => 'http://cyrusimap.org/ns/'); + $Self->ns(UF => 'http://cyrusimap.org/ns/userflag/'); + $Self->ns(SF => 'http://cyrusimap.org/ns/sysflag/'); + + return $Self; +} + +=head2 $self->tz($name) + +Returns a DateTime::TimeZone object for the given name, but caches +the result for speed. + +=cut + +sub tz { + my $Self = shift; + my $tzName = shift; + return $FLOATING unless defined $tzName; + return $UTC if $UTCLinks{$tzName}; + unless (exists $Self->{_tz}{$tzName}) { + $Self->{_tz}{$tzName} = DateTime::TimeZone->new(name => $tzName); + } + return $Self->{_tz}{$tzName}; +} + +=head2 $self->logger(sub { }) + +Sets a function to receive all log messages. Gets called with the first +argument being a level name, and then a list of items to log: + +e.g. + + $CalDAV->logger(sub { + my $level = shift; + return if ($level eq 'debug' and not $ENV{DEBUG_CALDAV}); + warn "LOG $level: $_\n" for @_; + }); + +=cut + +sub logger { + my $Self = shift; + + if ($@) { + $Self->{logger} = shift; + } + + return $Self->{logger}; +} + +=head2 $self->DeleteCalendar($calendarId) + +Delete the named calendar from the server (shorturl - see Net::DAVTalk) + +=cut + +=head2 $Cal->DeleteCalendar($calendarId) + +Delete the calendar with collection name $calendarId (full or relative path) + +e.g. + + $Cal->DeleteCalendar('Default'); + +=cut + +sub DeleteCalendar { + my ($Self, $calendarId) = @_; + + unless ($calendarId) { + confess 'Calendar not specified'; + } + + $Self->Request( + 'DELETE', + "$calendarId/", + ); + + return 1; +} + +sub _fixColour { + my $color = lc(shift || ''); + + return $color if $ColourNames{$color}; + return $DefaultCalendarColour unless $color =~ m/^\s*(\#[a-f0-9]{3,8})\s*$/; + $color = $1; + return uc($color) if length($color) == 7; + + # Optional digit is for transparency (RGBA) + if ( $color =~ m/^#(.)(.)(.).?$/ ) { + return uc "#$1$1$2$2$3$3"; + } + + # Last two digits are for transparency (RGBA) + if ( length($color) == 9 ) { + return uc(substr($color,0,7)); + } + + return $DefaultCalendarColour; +} + + +=head2 $self->GetCalendar($calendarId) + +Get a single calendar from the server by calendarId +(currently implemented very inefficiently as a get +of all calendars. Returns undef if the calendar +doesn't exist. + +e.g + my $Calendar = $CalDAV->GetCalendar('Default'); + +=cut + +sub GetCalendar { + my ($Self, $CalendarId) = @_; + my $Calendars = $Self->GetCalendars(); + die "No calendars" unless ($Calendars and @$Calendars); + my ($Calendar) = grep { $_->{id} eq $CalendarId } @$Calendars; + return $Calendar; +} + +=head2 $self->GetCalendars(Properties => []) + +Fetch all the calendars on the server. You can request additional +properties, but they aren't parsed well yet. + +e.g + + my $Calendars = $CalDAV->GetCalendars(); + foreach my $Cal (@$Calendars) { + # do stuff + } + +=cut + +sub GetCalendars { + my ($Self, %Args) = @_; + + # XXX To generalise for CPAN: + # XXX - the PROPFIND should be D:allprop unless $Args{Properties} is set + # XXX - return all properties as object attributes without renaming + # XXX - translate property names to our own liking within ME::CalDAV + + my %Properties = map { $_ => 1 } ( + 'D:displayname', + 'D:resourcetype', + 'A:calendar-color', + 'D:current-user-privilege-set', + 'D:acl', + 'A:calendar-order', + 'C:calendar-timezone', + 'D:sync-token', + 'D:supported-report-set', + 'C:supported-calendar-data', + @{$Args{Properties} || []}, + ); + + my $Response = $Self->Request( + 'PROPFIND', + '', + x('D:propfind', $Self->NS(), + x('D:prop', + map { x($_) } keys %Properties, + ), + ), + Depth => 1, + ); + + my @Calendars; + + my $NS_A = $Self->ns('A'); + my $NS_C = $Self->ns('C'); + my $NS_CY = $Self->ns('CY'); + my $NS_D = $Self->ns('D'); + foreach my $Response (@{$Response->{"{$NS_D}response"} || []}) { + next unless $Response->{"{$NS_D}href"}{content}; + my $href = uri_unescape($Response->{"{$NS_D}href"}{content}); + + # grab the short version of the path + my $calendarId = $Self->shortpath($href); + # and remove trailing slash always + $calendarId =~ s{/$}{}; + + foreach my $Propstat (@{$Response->{"{$NS_D}propstat"} || []}) { + next unless $Propstat->{"{$NS_D}prop"}{"{$NS_D}resourcetype"}{"{$NS_C}calendar"}; + + # XXX - this should be moved into ME::CalDAV::GetCalendars() + my $visData = $Propstat->{"{$NS_D}prop"}{"{$NS_C}X-FM-isVisible"}{content}; + my $isVisible = (not defined($visData) or $visData) ? $JSON::true : $JSON::false; + + my %Privileges = ( + mayAdmin => $JSON::false, + mayWrite => $JSON::false, + mayRead => $JSON::false, + mayReadFreeBusy => $JSON::false, + ); + + my $Priv = $Propstat->{"{$NS_D}prop"}{"{$NS_D}current-user-privilege-set"}{"{$NS_D}privilege"}; + $Priv = [] unless ($Priv and ref($Priv) eq 'ARRAY'); + foreach my $item (@$Priv) { + $Privileges{'mayAdmin'} = $JSON::true if $item->{"{$NS_CY}admin"}; + $Privileges{'mayWrite'} = $JSON::true if $item->{"{$NS_D}write-content"}; + $Privileges{'mayRead'} = $JSON::true if $item->{"{$NS_D}read"}; + $Privileges{'mayReadFreeBusy'} = $JSON::true if $item->{"{$NS_C}read-free-busy"}; + } + + my $CanSync; + my $Report = $Propstat->{"{$NS_D}prop"}{"{$NS_D}supported-report-set"}{"{$NS_D}supported-report"}; + $Report = [] unless ($Report and ref($Report) eq 'ARRAY'); + foreach my $item (@$Report) { + # XXX - do we want to check the other things too? + $CanSync = 1 if $item->{"{$NS_D}report"}{"{$NS_D}sync-collection"}; + } + + my $CanEvent; + my $Type = $Propstat->{"{$NS_D}prop"}{"{$NS_C}supported-calendar-data"}{"{$NS_C}calendar-data"}; + $Type = [] unless ($Type and ref($Type) eq 'ARRAY'); + foreach my $item (@$Type) { + next unless $item->{"\@content-type"}; + $CanEvent = 1 if $item->{"\@content-type"}{content} eq "application/event+json"; + } + + # XXX - temporary compat + $Privileges{isReadOnly} = $Privileges{mayWrite} ? $JSON::false : $JSON::true; + + my @ShareWith; + my $ace = $Propstat->{"{$NS_D}prop"}{"{$NS_D}acl"}{"{$NS_D}ace"}; + $ace = [] unless ($ace and ref($ace) eq 'ARRAY'); + foreach my $Acl (@$ace) { + next if $Acl->{"{$NS_D}protected"}; # ignore admin ACLs + next unless $Acl->{"{$NS_D}grant"}; + next unless $Acl->{"{$NS_D}grant"}{"{$NS_D}privilege"}; + next unless ref($Acl->{"{$NS_D}grant"}{"{$NS_D}privilege"}) eq 'ARRAY'; + # XXX - freeBusyPublic here? Or should we do it via the web server? + my $user = uri_unescape($Acl->{"{$NS_D}principal"}{"{$NS_D}href"}{content} // ''); + next unless $user =~ m{^/dav/principals/user/([^/]+)}; + my $email = $1; + next if $email eq 'admin'; + my %ShareObject = ( + email => $email, + mayAdmin => $JSON::false, + mayWrite => $JSON::false, + mayRead => $JSON::false, + mayReadFreeBusy => $JSON::false, + ); + foreach my $item (@{$Acl->{"{$NS_D}grant"}{"{$NS_D}privilege"}}) { + $ShareObject{'mayAdmin'} = $JSON::true if $item->{"{$NS_CY}admin"}; + $ShareObject{'mayWrite'} = $JSON::true if $item->{"{$NS_D}write-content"}; + $ShareObject{'mayRead'} = $JSON::true if $item->{"{$NS_D}read"}; + $ShareObject{'mayReadFreeBusy'} = $JSON::true if $item->{"{$NS_C}read-free-busy"}; + } + + push @ShareWith, \%ShareObject; + } + + my %Cal = ( + id => $calendarId, + name => ($Propstat->{"{$NS_D}prop"}{"{$NS_D}displayname"}{content} || $DefaultDisplayName), + href => $href, + color => _fixColour($Propstat->{"{$NS_D}prop"}{"{$NS_A}calendar-color"}{content}), + timeZone => $Propstat->{"{$NS_D}prop"}{"{$NS_C}calendar-timezone"}{content}, + isVisible => $isVisible, + precedence => int($Propstat->{"{$NS_D}prop"}{"{$NS_A}calendar-order"}{content} || 1), + syncToken => ($Propstat->{"{$NS_D}prop"}{"{$NS_D}sync-token"}{content} || ''), + shareWith => (@ShareWith ? \@ShareWith : $JSON::false), + canSync => ($CanSync ? $JSON::true : $JSON::false), + _can_event => ($CanEvent ? $JSON::true : $JSON::false), + %Privileges, + ); + + + push @Calendars, \%Cal; + } + } + + return \@Calendars; +} + +=head2 $self->NewCalendar($Args) + +Create a new calendar. The Args are the as the things returned by GetCalendars, +except that if you don't provide 'id' (same as shorturl), then a UUID will be +generated for you. It's recommended to not provide 'id' unless you need to +create a specific path for compatibility with other things, and to use 'name' +to identify the calendar for users. 'name' is stored as DAV:displayname. + +e.g. + + my $Id = $CalDAV->NewCalendar({name => 'My Calendar', color => 'aqua'}); + +(Color names will be translated based on the CSS name list) + +=cut + +sub NewCalendar { + my ($Self, $Args) = @_; + + unless (ref($Args) eq 'HASH') { + confess 'Invalid calendar'; + } + + # The URL should be "/$calendarId/" but this isn't true with Zimbra (Yahoo! + # Calendar). It will accept a MKCALENDAR at "/$calendarId/" but will rewrite + # the calendar's URL to be "/$HTMLEscapedDisplayName/". I'm sure MKCALENDAR + # should follow WebDAV's MKCOL method here, but it's not specified in CalDAV. + + # default values + $Args->{id} //= $Self->genuuid(); + $Args->{name} //= $DefaultDisplayName; + + my $calendarId = $Args->{id}; + + my @Properties; + + push @Properties, x('D:displayname', $Args->{name}); + + if (exists $Args->{isVisible}) { + push @Properties, x('C:X-FM-isVisible', ($Args->{isVisible} ? 1 : 0)); + } + + if (exists $Args->{color}) { + push @Properties, x('A:calendar-color', _fixColour($Args->{color})); + } + + if (exists $Args->{timeZone}) { + push @Properties, x('C:calendar-timezone', $Args->{timeZone}); + } + + if (exists $Args->{precedence}) { + unless (($Args->{precedence} // '') =~ /^\d+$/) { + confess "Invalid precedence ($Args->{precedence}) (expected int >= 0)"; + } + + push @Properties, x('A:calendar-order', $Args->{precedence}); + } + + $Self->Request( + 'MKCALENDAR', + "$calendarId/", + x('C:mkcalendar', $Self->NS(), + x('D:set', + x('D:prop', @Properties), + ), + ), + ); + + return $calendarId; +} + +=head2 $self->UpdateCalendar($Args) + +Like 'NewCalendar', but updates an existing calendar, and 'id' is required. +Returns the id, just like NewCalendar. + +=cut + +sub UpdateCalendar { + my ($Self, $Args, $Prev) = @_; + + unless (ref($Args) eq 'HASH') { + confess 'Invalid calendar'; + } + + my %Calendar = %{$Args}; + my $calendarId = $Calendar{id}; + + unless ($calendarId) { + confess 'Calendar not specified'; + } + + my @Params; + + if (defined $Calendar{name}) { + push @Params, x('D:displayname', $Calendar{name}); + } + + if (defined $Calendar{color}) { + push @Params, x('A:calendar-color', _fixColour($Calendar{color})); + } + + if (exists $Args->{timeZone}) { + push @Params, x('C:calendar-timezone', $Args->{timeZone}); + } + + if (exists $Calendar{isVisible}) { + push @Params, x('C:X-FM-isVisible', $Calendar{isVisible} ? 1 : 0); + } + + if (exists $Calendar{precedence}) { + unless (($Calendar{precedence} ||'') =~ /^\d+$/) { + confess "Invalid precedence ($Calendar{precedence})"; + } + + push @Params, x('A:calendar-order', $Calendar{precedence}); + } + + return $calendarId unless @Params; + + $Self->Request( + 'PROPPATCH', + "$calendarId/", + x('D:propertyupdate', $Self->NS(), + x('D:set', + x('D:prop', + @Params, + ), + ), + ), + ); + + return $calendarId; +} + +# Event methods + +=head2 $self->DeleteEvent($Event|$href) + +Given a single event or the href to the event, delete that event, +delete it from the server. + +Returns true. + +=cut + +sub DeleteEvent { + my ($Self) = shift; + my ($Event) = @_; + + confess "Need an event" unless $Event; + + $Event = { href => $Event, summary => $Event } unless ref($Event) eq 'HASH'; + + $Self->Request( + 'DELETE', + $Event->{href}, + ); + + return 1; +} + +=head2 $self->GetEvents($calendarId, %Args) + +Fetches some or all of the events in a calendar. + +Supported args: + + href => [] - perform a multi-get on just these fullpath urls. + after+before => ISO8601 - date range to query + +In scalar context returns an arrayref of events. In list context +returns both an arrayref of events and an arrayref of errors: + +e.g. + + my ($Events, $Errors) = $CalDAV->GetEvents('Default'); + +=cut + +sub GetEvents { + my ($Self, $calendarId, %Args) = @_; + + my $urls = $Self->GetEventLinks($calendarId, %Args); + + my @AllUrls = sort keys %$urls; + + my ($Events, $Errors, $Links) = $Self->GetEventsMulti($calendarId, \@AllUrls, %Args); + + return wantarray ? ($Events, $Errors, $Links) : $Events; +} + +=head2 $self->GetEventsMulti($calendarId, $Urls, %Args) + +Fetches the events in Urs from the calendar + +Supported args: + + * ContentType + * Version + +For the calendar-data response + +In scalar context returns an arrayref of events. In list context +returns an array of: + +* arrayref of events +* arrayref of errors: +* hash of href to getetag + +=cut + +sub GetEventsMulti { + my ($Self, $calendarId, $Urls, %Args) = @_; + + confess "Need a calendarId" unless $calendarId; + + my @Annotations; + my $AnnotNames = $Args{Annotations} || []; + foreach my $key (@$AnnotNames) { + my $name = ($key =~ m/:/ ? $key : "C:$key"); + push @Annotations, x($name); + } + + my %CalProps; + if ($Args{ContentType}) { + $CalProps{'content-type'} = $Args{ContentType}; + } + if ($Args{Version}) { + $CalProps{'version'} = $Args{Version}; + } + + my (@Events, @Errors, %Links); + + while (my @urls = splice(@$Urls, 0, $BATCHSIZE)) { + my $Response = $Self->Request( + 'REPORT', + "$calendarId/", + x('C:calendar-multiget', $Self->NS(), + x('D:prop', + x('C:calendar-data', \%CalProps), + x('D:getetag'), + @Annotations, + ), + map { x('D:href', $_) } @urls, + + ), + Depth => 1, + ); + + my $NS_A = $Self->ns('A'); + my $NS_C = $Self->ns('C'); + my $NS_D = $Self->ns('D'); + foreach my $Response (@{$Response->{"{$NS_D}response"} || []}) { + my $href = uri_unescape($Response->{"{$NS_D}href"}{content} // ''); + next unless $href; + foreach my $Propstat (@{$Response->{"{$NS_D}propstat"} || []}) { + my $etag = $Propstat->{"{$NS_D}prop"}{"{$NS_D}getetag"}{content}; + $Links{$href} = $etag; + my $Prop = $Propstat->{"{$NS_D}prop"}{"{$NS_C}calendar-data"}; + my $Data = $Prop->{content}; + next unless $Data; + + my $Event; + + if ($Prop->{'-content-type'} and $Prop->{'-content-type'} =~ m{application/event\+json}) { + # JSON event is in API format already + $Event = eval { decode_json($Data) }; + } + else { + # returns an array, but there should only be one UID per file + ($Event) = eval { $Self->vcalendarToEvents($Data) }; + } + + if ($@) { + push @Errors, $@; + next; + } + next unless $Event; + + if ($Args{Full}) { + $Event->{_raw} = $Data; + } + + $Event->{href} = $href; + $Event->{id} = $Self->shortpath($href); + + foreach my $key (@$AnnotNames) { + my $propns = $NS_C; + my $name = $key; + if ($key =~ m/(.*):(.*)/) { + $name = $2; + $propns = $Self->ns($1); + } + my $AData = $Propstat->{"{$NS_D}prop"}{"{$propns}$name"}{content}; + next unless $AData; + $Event->{annotation}{$name} = $AData; + } + + push @Events, $Event; + } + } + } + + return wantarray ? (\@Events, \@Errors, \%Links) : \@Events; +} + +=head2 $self->GetEventLinks($calendarId, %Args) + +Fetches the URLs of calendar events in a calendar. + +Supported args: + + after+before => ISO8601 - date range to query + +returns a hash of href to etag + +=cut + +sub GetEventLinks { + my ($Self, $calendarId, %Args) = @_; + confess "Need a calendarId" unless $calendarId; + + my @Extra; + if ($Args{AlwaysRange} || $Args{after} || $Args{before}) { + my $Start = _wireDate($Args{after} || $BoT); + my $End = _wireDate($Args{before} || $EoT); + push @Extra, x('C:time-range', { + start => $Start->strftime('%Y%m%dT000000Z'), + end => $End->strftime('%Y%m%dT000000Z'), + }); + } + + my $Response = $Self->Request( + 'REPORT', + "$calendarId/", + x('C:calendar-query', $Self->NS(), + x('D:prop', + x('D:getetag'), + ), + x('C:filter', + x('C:comp-filter', { name => 'VCALENDAR' }, + x('C:comp-filter', { name => 'VEVENT' }, + @Extra, + ), + ), + ), + ), + Depth => 1, + ); + + my (%Links, @Errors); + + my $NS_A = $Self->ns('A'); + my $NS_C = $Self->ns('C'); + my $NS_D = $Self->ns('D'); + foreach my $Response (@{$Response->{"{$NS_D}response"} || []}) { + my $href = uri_unescape($Response->{"{$NS_D}href"}{content} // ''); + next unless $href; + foreach my $Propstat (@{$Response->{"{$NS_D}propstat"} || []}) { + my $etag = $Propstat->{"{$NS_D}prop"}{"{$NS_D}getetag"}{content}; + $Links{$href} = $etag; + } + } + + return \%Links; +} + +=head2 $self->GetEvent($href) + +Just get a single event (calls GetEvents with that href) + +=cut + +sub GetEvent { + my ($Self, $href, %Args) = @_; + + # XXX - API + my $calendarId = $href; + $calendarId =~ s{/[^/]*$}{}; + + my ($Events, $Errors) = $Self->GetEventsMulti($calendarId, [$Self->fullpath($href)], %Args); + + die "Errors @$Errors" if @$Errors; + die "Multiple items returned for $href" if @$Events > 1; + + return $Events->[0]; +} + +=head2 $self->GetFreeBusy($calendarId, %Args) + +Like 'GetEvents' but uses a free-busy-query and then generates +synthetic events out of the result. + +Doesn't have a 'href' parameter, just the before/after range. + +=cut + +sub GetFreeBusy { + my ($Self, $calendarId, %Args) = @_; + + # validate parameters {{{ + + confess "Need a calendarId" unless $calendarId; + + my @Query; + if ($Args{AlwaysRange} || $Args{after} || $Args{before}) { + my $Start = _wireDate($Args{after} || $BoT); + my $End = _wireDate($Args{before} || $EoT); + + push @Query, + x('C:time-range', { + start => $Start->strftime('%Y%m%dT000000Z'), + end => $End->strftime('%Y%m%dT000000Z'), + }); + } + + # }}} + + my $Response = $Self->Request( + 'REPORT', + "$calendarId/", + x('C:free-busy-query', $Self->NS(), + @Query, + ), + Depth => 1, + ); + + my $Data = eval { vcard2hash($Response->{content}, multival => ['rrule'], only_one => 1) } + or confess "Error parsing VFreeBusy data: $@"; + + my @result; + my @errors; + my $now = DateTime->now(); + foreach my $item (@{$Data->{objects}[0]{objects}}) { + next unless $item->{type} eq 'vfreebusy'; + foreach my $line (@{$item->{properties}{freebusy}}) { + my ($Start, $End) = split '/', $line->{value}; + my ($StartTime, $IsAllDay) = $Self->_makeDateObj($Start, 'UTC', 'UTC'); + my $EndTime; + if ($End =~ m/^[+-]?P/i) { + my $Duration = eval { DateTime::Format::ICal->parse_duration(uc $End) } + || next; + $EndTime = $StartTime->clone()->add($Duration); + } else { + ($EndTime) = $Self->_makeDateObj($End, 'UTC', 'UTC'); + } + my $duration = $Self->_make_duration($EndTime->subtract_datetime($StartTime)); + my $NewEvent = { + timeZone => 'Etc/UTC', + start => $StartTime->iso8601(), + duration => $duration, + title => ($Args{name} // ''), + isAllDay => ($IsAllDay ? $JSON::true : $JSON::false), + updated => $now->iso8601(), + }; + + # Generate a uid that should remain the same for this freebusy entry + $NewEvent->{uid} = _hexkey($NewEvent) . '-freebusyauto'; + $NewEvent->{isAllDay} = + $NewEvent->{isAllDay} ? $JSON::true : $JSON::false; + push @result, $NewEvent; + } + } + + return (\@result, \@errors); +} + +=head2 $self->SyncEvents($calendarId, %Args) + +Like GetEvents, but if you pass a syncToken argument, then it will +fetch changes since that token (obtained from an earlier GetCalendars +call). + +In scalar context still just returns new events, in list context returns +Events, Removed and Errors. + +e.g. + + my ($Events, $Removed, $Errors) = $CalDAV->SyncEvents('Default', syncToken => '...'); + +=cut + +sub SyncEvents { + my ($Self, $calendarId, %Args) = @_; + + my ($Added, $Removed, $Errors, $SyncToken) = $Self->SyncEventLinks($calendarId, %Args); + + my @AllUrls = sort keys %$Added; + + my ($Events, $ThisErrors, $Links) = $Self->GetEventsMulti($calendarId, \@AllUrls, %Args); + push @$Errors, @$ThisErrors; + + return wantarray ? ($Events, $Removed, $Errors, $SyncToken, $Links) : $Events; +} + +=head2 $self->SyncEventLinks($calendarId, %Args) + +Like GetEventLinks, but if you pass a syncToken argument, then it will +fetch changes since that token (obtained from an earlier GetCalendars +or SyncEvent* call). + +In scalar context still just returns Added, in list context returns +Added, Removed, Errors and new token: + +* Added: hash of href to etag - added or changed +* Removed: array of href +* Errors: array of descritive string +* NewToken: scalar opaque DAV:sync-token + +e.g. + + my ($Added, $Removed, $Errors, $NewToken) + = $CalDAV->SyncEventLinks('Default', syncToken => '...'); + +=cut + +sub SyncEventLinks { + my ($Self, $calendarId, %Args) = @_; + + confess "Need a calendarId" unless $calendarId; + + my $Response = $Self->Request( + 'REPORT', + "$calendarId/", + x('D:sync-collection', $Self->NS(), + x('D:sync-token', ($Args{syncToken} ? ($Args{syncToken}) : ())), + x('D:sync-level', 1), + x('D:prop', + x('D:getetag'), + ), + ), + ); + + my $NS_A = $Self->ns('A'); + my $NS_C = $Self->ns('C'); + my $NS_D = $Self->ns('D'); + + my $SyncToken = $Response->{"{$NS_D}sync-token"}{content}; + confess "NO SYNC TOKEN RETURNED " . Dumper($Response) unless $SyncToken; + + my (%Added, @Removed, @Errors); + foreach my $Response (@{$Response->{"{$NS_D}response"} || []}) { + my $href = uri_unescape($Response->{"{$NS_D}href"}{content} // ''); + next unless $href; + + unless ($Response->{"{$NS_D}propstat"}) { + push @Removed, $href; + next; + } + + foreach my $Propstat (@{$Response->{"{$NS_D}propstat"} || []}) { + my $status = $Propstat->{"{$NS_D}status"}{content}; + if ($status =~ m/ 200 /) { + my $etag = $Propstat->{"{$NS_D}prop"}{"{$NS_D}getetag"}{content}; + $Added{$href} = $etag; + } + else { + push @Errors, "Odd status $status"; + } + } + } + + return (\%Added, \@Removed, \@Errors, $SyncToken); +} + +=head2 $self->NewEvent($calendarId, $Args) + +Create a new event in the named calendar. If you don't specify 'uid' then +a UUID will be created. You should only specify the UID if you need to for +syncing purposes - it's better to auto-generate otherwise. + +Returns the href, but also updates 'uid' in $Args. + +Also updates 'sequence'. + +e.g. + + my $href = $CalDAV->NewEvent('Default', $Args); + my $newuid = $Args->{uid}; + +=cut + +sub NewEvent { + my ($Self, $calendarId, $Args) = @_; + + confess "Need a calendarId" unless $calendarId; + + confess "invalid event" unless ref($Args) eq 'HASH'; + + my $UseEvent = delete $Args->{_put_event_json}; + + # calculate updated sequence numbers + unless (exists $Args->{sequence}) { + $Args->{sequence} = 1; + } + + if ($Args->{exceptions}) { + foreach my $recurrenceId (sort keys %{$Args->{exceptions}}) { + my $val = $Args->{exceptions}{$recurrenceId}; + next unless $val; + next if exists $val->{sequence}; + + $val->{sequence} = $Args->{sequence}; + } + } + + $Args->{uid} //= $Self->genuuid(); + my $uid = $Args->{uid}; + my $path = $uid; + $path =~ tr/[a-zA-Z0-9\@\.\_\-]//cd; + my $href = "$calendarId/$path.ics"; + + if ($UseEvent) { + $Self->Request( + 'PUT', + $href, + encode_json($Args), + 'Content-Type' => 'application/event+json', + ); + } + else { + my $VCalendar = $Self->_argsToVCalendar($Args); + $Self->Request( + 'PUT', + $href, + $VCalendar->as_string(), + 'Content-Type' => 'text/calendar', + ); + } + + return $href; +} + +=head2 $self->UpdateEvent($href, $Args) + +Like NewEvent, but you only need to specify keys that you want to change, +and it takes the full href to the card instead of the containing calendar. + +=cut + +sub UpdateEvent { + my ($Self, $href, $Args) = @_; + + my $UseEvent = delete $Args->{_put_event_json}; + + my ($OldEvent, $NewEvent) = $Self->_updateEvent($href, $Args); + + if ($UseEvent) { + $Self->Request( + 'PUT', + $href, + encode_json($NewEvent), + 'Content-Type' => 'application/event+json', + ); + } + else { + my $VCalendar = $Self->_argsToVCalendar($NewEvent); + $Self->Request( + 'PUT', + $href, + $VCalendar->as_string(), + 'Content-Type' => 'text/calendar', + ); + } + + return 1; +} + +sub _updateEvent { + my ($Self, $href, $Args) = @_; + + my $OldEvent = $Self->GetEvent($href); + + confess "Error getting old event for $href" + unless $OldEvent; + + my %NewEvent; + + foreach my $Property (keys %EventKeys) { + if (exists $Args->{$Property}) { + if (defined $Args->{$Property}) { + $NewEvent{$Property} = $Args->{$Property}; + } + } + elsif (exists $OldEvent->{$Property}) { + $NewEvent{$Property} = $OldEvent->{$Property}; + } + } + + # calculate updated sequence numbers + unless (exists $Args->{sequence}) { + $NewEvent{sequence} = ($OldEvent->{sequence} || 0) + 1; + } + + if ($NewEvent{exceptions}) { + foreach my $recurrenceId (sort keys %{$NewEvent{exceptions}}) { + my $val = $NewEvent{exceptions}{$recurrenceId}; + next unless $val; + next if exists $val->{sequence}; + + my $old = $OldEvent->{exceptions}{$recurrenceId}; + my $sequence = $NewEvent{sequence}; + if ($old && exists $old->{sequence}) { + $sequence = $old->{sequence} + 1 unless $sequence > $old->{sequence}; + } + $val->{sequence} = $sequence; + } + } + + $NewEvent{href} = $href; + + return ($OldEvent, \%NewEvent); +} + +=head2 $self->AnnotateEvent($href, $Args) + +Instead of actually changing an event itself, use proppatch to +add or remove properties on the event. + +=cut + +sub AnnotateEvent { + my ($Self, $href, $Args) = @_; + + my $OldEvent = $Self->GetEvent($href); + + confess "Error getting old event for $href" + unless $OldEvent; + + my @Set; + my @Remove; + foreach my $key (sort keys %$Args) { + my $name = ($key =~ m/:/ ? $key : "C:$key"); + if (defined $Args->{$key}) { + push @Set, x($name, $Args->{$key}); + } + else { + push @Remove, x($name); + } + } + + my @Params; + push @Params, x('D:set', x('D:prop', @Set)) if @Set; + push @Params, x('D:remove', x('D:prop', @Remove)) if @Remove; + return undef unless @Params; + + $Self->Request( + 'PROPPATCH', + $href, + x('D:propertyupdate', $Self->NS(), @Params), + ); + + return 1; +} + +=head2 $self->MoveEvent($href, $newCalendarId) + +Move an event into a new calendar. Returns the new href. + +=cut + +sub MoveEvent { + my ($Self, $href, $newCalendarId) = @_; + + my $OldEvent = $Self->GetEvent($href); + + return unless $OldEvent; + + my $dest = $href; + $dest =~ s{.*/}{$newCalendarId/}; + return if $href eq $dest; + + $Self->Request( + 'MOVE', + $href, + undef, + 'Destination' => $Self->fullpath($dest), + ); + + warn "CAL: MoveEvent $Self->{user} ($href => $dest)\n"; + + return $dest; +} + +sub _BYDAY2byDay { + my ($BYDAY) = @_; + + my ($Count, $Day) = $BYDAY =~ /^([-+]?\d+)?(\w\w)$/; + + unless ($Day) { + confess 'Recurrence BYDAY-weekday not specified'; + } + + unless ($WeekDayNames{$Day}) { + confess 'Invalid recurrence BYDAY-weekday'; + } + + if ($Count) { + unless (($Count >= -53) and ($Count <= 53)) { + confess 'Recurrence BYDAY-ordwk is out of range'; + } + } + + return { + day => $WeekDayNames{$Day}, + $Count ? (nthOfPeriod => int($Count)) : (), + }; +} + +sub _byDay2BYDAY { + my ($byDay) = @_; + + unless (defined $byDay) { + confess 'Invalid recurrence byDay'; + } + + unless (ref $byDay eq 'HASH') { + confess 'Recurrence byDay is not an object'; + } + + my $Day = $WeekDayNamesReverse{$byDay->{day}}; + unless ($Day) { + confess 'Recurrence byDay is not a known day'; + } + my $Prefix = ''; + $Prefix = int($byDay->{nthOfPeriod}) if $byDay->{nthOfPeriod}; + + return $Prefix . uc($Day); +} + +sub _makeDateObj { + my $Self = shift; + my $DateStr = shift; + my $TZStr = shift; + my $TargetTz = shift; + + my ($Date, $HasTime) = _vDate($DateStr); + + # if it's all day, return it immediately + return ($Date, 1) unless $HasTime; + + # Do the timezone manipulation as required + $Date->set_time_zone($Self->tz($TZStr)) if $TZStr; + $Date->set_time_zone($Self->tz($TargetTz)) if $TargetTz; + + return ($Date, 0); +} + +sub _getDateObj { + my $Self = shift; + my $Calendar = shift; + my $VItem = shift; + my $TargetTz = shift; + + my $TimeZone = $Self->_getTimeZone($Calendar, $VItem); + my ($Date, $IsAllDay) = $Self->_makeDateObj($VItem->{value}, $TimeZone, $TargetTz); + + return (wantarray ? ($Date, $TimeZone, $IsAllDay) : $Date); +} + +sub _getDateObjMulti { + my $Self = shift; + my $Calendar = shift; + my $VItem = shift; + my $TargetTz = shift; + + my @Dates; + + my $TimeZone = $Self->_getTimeZone($Calendar, $VItem); + foreach my $Value (split /,/, $VItem->{value}) { + # XXX - handle $V2 sanely + if (lc($VItem->{params}{value}[0] || '') eq 'period') { + ($Value, my $V2) = split /\//, $Value; + } + my ($Date, $IsAllDay) = $Self->_makeDateObj($Value, $TimeZone, $TargetTz); + push @Dates, $Date; + } + + return @Dates; +} + +# Exclude DTSTAMP from auto uid generation +sub _hexkey { + my $VEvent = shift; + my $updated = delete $VEvent->{properties}->{updated}; + my $d = Data::Dumper->new([$VEvent]); + $d->Indent(0); + $d->Sortkeys(1); + my $Key = sha1_hex($d->Dump()); + $VEvent->{properties}->{updated} = $updated if defined $updated; + return $Key; +} + +sub _saneuid { + my $uid = shift; + return unless $uid; + return if $uid =~ m/\s/; + return if $uid =~ m/[\x7f-\xff]/; + # any other sanity checks? + return 1; +} + +sub _makeParticipant { + my ($Self, $Calendar, $Participants, $VAttendee, $role) = @_; + + my $id = $VAttendee->{value}; + return unless $id; + $id =~ s/^mailto://i; + return if $id eq ''; + + $Participants->{$id} ||= {}; + + # XXX - if present on one but not the other, take the "best" version + $Participants->{$id}{name} = $VAttendee->{params}{"cn"}[0] // ""; + $Participants->{$id}{email} = $id; + $Participants->{$id}{kind} = lc $VAttendee->{params}{"cutype"}[0] + if $VAttendee->{params}{"cutype"}; + push @{$Participants->{$id}{roles}}, $role; + # we don't support locationId yet + if ($VAttendee->{params}{"partstat"}) { + $Participants->{$id}{scheduleStatus} = lc($VAttendee->{params}{"partstat"}[0] // "needs-action"); + } + if ($VAttendee->{params}{"role"}) { + push @{$Participants->{$id}{roles}}, 'chair' + if uc $VAttendee->{params}{"role"}[0] eq 'CHAIR'; + $Participants->{$id}{schedulePriority} = 'optional' + if uc $VAttendee->{params}{"role"}[0] eq 'OPT-PARTICIPANT'; + $Participants->{$id}{schedulePriority} = 'non-participant' + if uc $VAttendee->{params}{"role"}[0] eq 'NON-PARTICIPANT'; + } + if ($VAttendee->{params}{"rsvp"}) { + $Participants->{$id}{scheduleRSVP} = lc($VAttendee->{params}{"rsvp"}[0] // "") eq 'yes' ? $JSON::true : $JSON::false; + } + if (exists $VAttendee->{params}{"x-dtstamp"}) { + my ($Date) = eval { $Self->_makeDateObj($VAttendee->{params}{"x-dtstamp"}[0], 'UTC', 'UTC') }; + $Participants->{$id}{"scheduleUpdated"} = $Date->iso8601() . 'Z' if $Date; + } + # memberOf is not supported + + if (exists $VAttendee->{params}{"x-sequence"}) { + $Participants->{$id}{"x-sequence"} = $VAttendee->{params}{"x-sequence"}[0] // ""; + } +} + +sub _make_duration { + my ($Self, $dtdur, $IsAllDay) = @_; + + my ($w, $d, $H, $M, $S) = ( + $dtdur->weeks, + $dtdur->days, + $dtdur->hours, + $dtdur->minutes, + $dtdur->seconds, + ); + + return 'PT0S' unless ($w || $d || $H || $M || $S); + + my @bits = ('P'); + push @bits, ($w, 'W') if $w; + push @bits, ($d, 'D') if $d; + if (not $IsAllDay and ($H || $M || $S)) { + push @bits, 'T'; + push @bits, ($H, 'H') if $H; + push @bits, ($M, 'M') if $M; + push @bits, ($S, 'S') if $S; + } + + return join ('', @bits); +} + +=head2 $NewEvent = Net::CalDAVTalk->NormaliseEvent($Event); + +Doesn't change the original event, but removes any keys which are the same as their default value + +=cut + +sub NormaliseEvent { + my ($class, $Event, $Root) = @_; + + $Root ||= ''; + + my %Copy = %$Event; + + # XXX: patches need to be normalised as well... + my $Spec = $EventKeys{$Root}; + foreach my $key (keys %$Event) { + delete $Copy{$key} unless $Spec->{$key}; + } + foreach my $key (sort keys %$Spec) { + # remove if it's the default + if ($Spec->{$key}[1] eq 'object') { + my $Item = delete $Copy{$key}; + next unless $Item; # no object + if ($Spec->{$key}[0]) { + $Copy{$key} = [map { $class->NormaliseEvent($_, $key) } @$Item]; + } + else { + $Copy{$key} = $class->NormaliseEvent($Item, $key); + } + } + elsif ($Spec->{$key}[1] eq 'bool') { + delete $Copy{$key} if !!$Spec->{$key}[3] == !!$Copy{$key}; + } + elsif ($Spec->{$key}[1] eq 'mailto') { + $Copy{$key} = lc $Copy{$key} if $Copy{$key}; + } + else { + delete $Copy{$key} if _safeeq($Spec->{$key}[3], $Copy{$key}); + } + } + + return \%Copy; +} + +=head2 Net::CalDAVTalk->CompareEvents($Event1, $Event2); + +Returns true if the events are identical + +=cut + +sub CompareEvents { + my ($class, $Event1, $Event2) = @_; + + my $E1 = $class->NormaliseEvent($Event1); + my $E2 = $class->NormaliseEvent($Event2); + + return _safeeq($E1, $E2); +} + + +sub _getEventsFromVCalendar { + my ($Self, $VCalendar) = @_; + + my $CalendarData = eval { vcard2hash($VCalendar, multival => ['rrule'], only_one => 1) } + or confess "Error parsing VCalendar data: $@\n\n$VCalendar"; + + my @Events; + + foreach my $Calendar (@{$CalendarData->{objects} || []}) { + next unless lc $Calendar->{type} eq 'vcalendar'; + + my $method = $Calendar->{properties}{method}[0]{value}; + my $prodid = $Calendar->{properties}{prodid}[0]{value}; + + foreach my $VEvent (@{$Calendar->{objects} || []}) { + next unless lc $VEvent->{type} eq 'vevent'; + + # parse simple component properties {{{ + + my %Properties + = map { $_ => $VEvent->{properties}{$_}[0] } + keys %{$VEvent->{properties}}; + + my $uid = $Properties{uid}{value}; + # Case: UID is badly broken or missing - + # let's just calculate a UID based on the incoming data. This + # is the 'ICS sync url with no UIDs in it' case from BTS-3205, + # http://mozorg.cdn.mozilla.net/media/caldata/DutchHolidays.ics + $uid = _hexkey($VEvent) . '-syncauto' unless _saneuid($uid); + + my $ShowAsFree = (lc($Properties{transp}{value} || '')) eq 'transparent'; + + # clean up whitespace on text fields + foreach my $Property (qw{description location summary}) { + next unless defined $Properties{$Property}{value}; + $Properties{$Property}{value} =~ s/^\s+//gs; + $Properties{$Property}{value} =~ s/\s+$//gs; + } + + my @description; + push @description, $Properties{description}{value} + if defined $Properties{description}{value}; + + # }}} + + # parse time component properties {{{ + + my ($IsAllDay, $Start, $StartTimeZone, $End, $EndTimeZone) = ('') x 5; + + confess "$uid: DTSTART not specified" unless defined $Properties{dtstart}{value}; + + ($Start, $StartTimeZone, $IsAllDay) = $Self->_getDateObj($Calendar, $Properties{dtstart}); + + if (defined $Properties{dtend}{value}) { + if (defined $Properties{duration}{value}) { + warn "$uid: DTEND and DURATION cannot both be set"; + } + + ($End, $EndTimeZone) = $Self->_getDateObj($Calendar, $Properties{dtend}); + } + elsif (defined $Properties{duration}{value}) { + my $Duration = DateTime::Format::ICal->parse_duration(uc $Properties{duration}{value}); + $End = $Start->clone()->add($Duration); + $EndTimeZone = $StartTimeZone; + } + else { + $End = $Start->clone(); + $EndTimeZone = $StartTimeZone; + } + + if (DateTime->compare($Start, $End) > 0) { + # swap em! + ($Start, $End) = ($End, $Start); + ($StartTimeZone, $EndTimeZone) = ($EndTimeZone, $StartTimeZone); + } + + if ($IsAllDay and $StartTimeZone) { + warn "$uid: AllDay event with timezone $StartTimeZone specified"; + } + + # if one is set, make sure they are both set + $StartTimeZone ||= $EndTimeZone; + $EndTimeZone ||= $StartTimeZone; + + # }}} + + my %Recurrence; + + if (exists $Properties{rrule}) { + my %RRULE; + + foreach my $RRULE (@{$Properties{rrule}{values}}) { + my ($Key,$Value) = split '=', $RRULE; + next unless defined $Value; + + $RRULE{lc $Key} = $Value; + } + + # parse simple recurrence properties {{{ + + if (exists $RRULE{freq}) { + my $freq = lc $RRULE{freq}; + unless (grep { $_ eq $freq } @Frequencies) { + confess "$uid: Invalid recurrence FREQ ($RRULE{freq})"; + } + + $Recurrence{frequency} = $freq; + } + else { + confess "$uid: Recurrence FREQ not specified"; + } + + if (exists $RRULE{interval}) { + unless ($RRULE{interval} =~ /^\d+$/) { + confess "$uid: Invalid recurrence INTERVAL ($RRULE{interval})"; + } + my $interval = int $RRULE{interval}; + + if ($interval == 0) { + confess "$uid: Recurrence INTERVAL is out of range ($RRULE{interval})"; + } + + # default == 1, so don't set a key for it + if ($interval > 1) { + $Recurrence{interval} = $interval; + } + } + + if (exists $RRULE{rscale}) { + $Recurrence{rscale} = lc $RRULE{rscale}; + $Recurrence{skip} = lc $RRULE{skip} if $RRULE{skip}; + } + + if (exists $RRULE{wkst}) { + my $wkst = lc $RRULE{wkst}; + unless ($WeekDayNames{$wkst}) { + confess "$uid: Invalid recurrence WKST ($RRULE{wkst})"; + } + + # default is Monday, so don't set a key for it + if ($wkst ne 'mo') { + $Recurrence{firstDayOfWeek} = $WeekDayNames{$wkst}; + } + } + + if (exists $RRULE{byday}) { + my @byDays; + + foreach my $BYDAY (split ',', $RRULE{byday}) { + push @byDays, _BYDAY2byDay(lc $BYDAY); + } + + $Recurrence{byDay} = \@byDays if @byDays; + } + + if (exists $RRULE{bymonth}) { + foreach my $BYMONTH (split ',', $RRULE{bymonth}) { + unless ($BYMONTH =~ /^\d+L?$/) { + confess "$uid: Invalid recurrence BYMONTH ($BYMONTH, $RRULE{bymonth})"; + } + + push @{$Recurrence{byMonth}}, "$BYMONTH"; + } + } + + if (exists $RRULE{count}) { + if (exists $RRULE{until}) { + #confess "$uid: Recurrence COUNT and UNTIL cannot both be set"; + # seen in the wild: PRODID:-//dmfs.org//mimedir.icalendar//EN + delete $RRULE{until}; + } + + unless ($RRULE{count} =~ /^\d+$/) { + confess "$uid: Invalid recurrence COUNT ($RRULE{count})"; + } + + $Recurrence{count} = int $RRULE{count}; + } + + if (exists $RRULE{until}) { + # rfc5545 3.3.10 - UNTIL must be in DTSTART timezone, but both + # google and iCloud store it in Z, so we will too as per rfc2445. + my ($Until, $IsAllDay) = $Self->_makeDateObj($RRULE{until}, $StartTimeZone, $StartTimeZone); + $Recurrence{until} = $Until->iso8601(); + } + + # }}} + + # parse generic recurrence properties {{{ + + foreach my $Property (keys %RecurrenceProperties) { + if (defined $RRULE{$Property}) { + foreach my $Value (split ',', $RRULE{$Property}) { + my ($Valid, $Min) = $RecurrenceProperties{$Property}{signed} + ? ('[-+]?[1-9]\d*', ($RecurrenceProperties{$Property}{max} * -1)) + : ('\d+', 0); + + unless ($Value =~ /^$Valid$/) { + confess "$uid: Invalid recurrence $Property ($Value)"; + } + + unless (($Value >= $Min) and ($Value <= $RecurrenceProperties{$Property}{max})) { + confess "$uid: Recurrence $Property is out of range ($Value)"; + } + + push @{$Recurrence{$RecurrenceProperties{$Property}{name}}}, int $Value; + } + } + } + + # }}} + } + + my %Overrides; + if (exists $VEvent->{properties}{exdate}) { + foreach my $Item (@{$VEvent->{properties}{exdate}}) { + foreach my $Date ($Self->_getDateObjMulti($Calendar, $Item, $StartTimeZone)) { + $Overrides{$Date->iso8601()} = $JSON::null; + } + } + } + + if ($VEvent->{properties}{rdate}) { + # rdate = "RDATE" rdtparam ":" rdtval *("," rdtval) CRLF + foreach my $Item (@{$VEvent->{properties}{rdate}}) { + foreach my $Date ($Self->_getDateObjMulti($Calendar, $Item, $StartTimeZone)) { + $Overrides{$Date->iso8601()} = {}; + } + } + } + + # parse alarms {{{ + + my %Alerts; + foreach my $VAlarm (@{$VEvent->{objects} || []}) { + next unless lc $VAlarm->{type} eq 'valarm'; + + my %AlarmProperties + = map { $_ => $VAlarm->{properties}{$_}[0] } + keys %{$VAlarm->{properties}}; + + my $alarmuid = $AlarmProperties{uid}{value} || _hexkey($VAlarm) . '-alarmauto'; + + my %Alert; + + my $AlarmAction = lc $AlarmProperties{action}{value}; + next unless $AlarmAction; + + my %Action; + + if ($AlarmAction eq 'display') { + $Action{type} = 'display'; + } + elsif ($AlarmAction eq 'email') { + $Action{type} = 'email'; + + $Action{to} = [ + map { my ($x) = $_->{value} =~ m/^(?:mailto:)?(.*)/i; { email => $x } } + @{$VAlarm->{properties}{attendee} // []} + ]; + } + elsif ($AlarmAction eq 'uri') { + $Action{type} = 'uri'; + $Action{uri} = $VAlarm->{properties}{uri} // []; + } + elsif ($AlarmAction eq 'audio') { + # audio alerts aren't the same as popups, but for now... + $Action{type} = 'display'; + } + elsif ($AlarmAction eq 'none') { + next; + } + else { + warn "$uid: UNKNOWN VALARM ACTION $AlarmAction"; + next; + } + + if ($AlarmProperties{acknowledged}) { + my $date = $Self->_getDateObj($Calendar, $AlarmProperties{acknowledged}, 'UTC'); + $Action{acknowledged} = $date->iso8601() . 'Z'; + } + + my $Trigger = $AlarmProperties{trigger}{value} + || next; + + my $Related = (lc ($AlarmProperties{trigger}{params}{related}[0] || '') eq 'end') + ? 'end' + : 'start'; + + my $Duration; + if ($Trigger =~ m/^[+-]?P/i) { + $Duration = eval { DateTime::Format::ICal->parse_duration(uc $Trigger) } + || next; + + } else { + my $AlertDate = $Self->_getDateObj($Calendar, $AlarmProperties{trigger}, $StartTimeZone); + $Duration = $AlertDate->subtract_datetime($Related eq 'end' ? $End : $Start); + } + + if ($Duration->is_negative()) { + $Duration = $Duration->inverse(); + $Alert{relativeTo} = "before-$Related"; + } + else { + $Alert{relativeTo} = "after-$Related"; + } + + $Alert{action} = \%Action; + $Alert{offset} = $Self->_make_duration($Duration); + + $Alerts{$alarmuid} = \%Alert; + } + + # }}} + + # parse attendees {{{ + + my %Participants; + for my $VOrganizer (@{$VEvent->{properties}{organizer} || []}) { + $Self->_makeParticipant($Calendar, \%Participants, $VOrganizer, 'owner'); + } + for my $VAttendee (@{$VEvent->{properties}{attendee} || []}) { + $Self->_makeParticipant($Calendar, \%Participants, $VAttendee, 'attendee'); + } + + # }}} + + # parse attachments {{{ + + my %Links; + foreach my $Attach (@{$VEvent->{properties}{attach} || []}) { + next unless $Attach->{value}; + next unless grep { $Attach->{value} =~ m{^$_://} } qw{http https ftp}; + + my $uri = $Attach->{value}; + my $filename = $Attach->{params}{filename}[0]; + # XXX - mime guessing? + my $mime = $Attach->{params}{fmttype}[0]; + if (not defined $mime) { + $::MimeTypes ||= MIME::Types->new; + my $MimeTypeObj = $::MimeTypes->mimeTypeOf($filename); + $mime = $MimeTypeObj->type() if $MimeTypeObj; + } + + my $size = $Attach->{params}{size}[0]; + + $Links{$uri} = { + href => $uri, + rel => 'enclosure', + defined $filename ? (title => $filename) : (), + defined $mime ? (type => $mime) : (), + defined $size ? (size => 0+$size) : (), + }; + } + foreach my $URL (@{$VEvent->{properties}{url} || []}) { + my $uri = $URL->{value}; + next unless $uri; + $Links{$uri} = { href => $uri }; + } + + # }}} + + # ============= Metadata + my %Event = (uid => $uid); + # no support for relatedTo yet + $Event{prodId} = $prodid; + if ($Properties{created}{value}) { + # UTC item + my $Date = eval { $Self->_getDateObj($Calendar, $Properties{created}, 'UTC') }; + $Event{created} = $Date->iso8601() . 'Z' if $Date; + } + if ($Properties{dtstamp}{value}) { + # UTC item + my $Date = eval { $Self->_getDateObj($Calendar, $Properties{dtstamp}, 'UTC') }; + $Event{updated} = $Date->iso8601() . 'Z' if $Date; + } + $Event{updated} ||= DateTime->now->iso8601(); + $Event{sequence} = int($Properties{sequence}{value}) if $Properties{sequence}; + $Event{method} = $method if $method; + + # ============= What + $Event{title} = $Properties{summary}{value} if $Properties{summary}; + $Event{description} = join("\n", @description) if @description; + # htmlDescription is not supported + $Event{links} = \%Links if %Links; + my $language; + if ($Properties{description} and $Properties{description}{params}{language}) { + $language = $Properties{description}{params}{language}[0]; + } + if ($Properties{summary} and $Properties{summary}{params}{language}) { + $language = $Properties{summary}{params}{language}[0]; + } + $Event{locale} = $language if $language; + # translations is not supported + + # ============= Where + # XXX - support more structured representations from VEVENTs + if ($Properties{location}{value}) { + $Event{locations}{location} = { name => $Properties{location}{value} }; + } + if (not $IsAllDay and $StartTimeZone and $StartTimeZone ne $EndTimeZone) { + $Event{locations}{end} = { rel => 'end', timeZone => $EndTimeZone }; + } + + # ============= When + $Event{isAllDay} = $IsAllDay ? $JSON::true : $JSON::false; + $Event{start} = $Start->iso8601() if ref($Start); + $Event{timeZone} = $StartTimeZone if not $IsAllDay; + my $duration = $Self->_make_duration($End->subtract_datetime($Start), $IsAllDay); + $Event{duration} = $duration if $duration; + + $Event{recurrenceRule} = \%Recurrence if %Recurrence; + $Event{recurrenceOverrides} = \%Overrides if %Overrides; + + # ============= Scheduling + if ($Properties{status}{value}) { + $Event{status} = lc($Properties{status}{value}) if lc($Properties{status}{value}) ne 'confirmed'; + } + if ($Properties{transp}{value}) { + $Event{showAsFree} = $JSON::true if lc($Properties{transp}{value}) eq 'transparent'; + } + foreach my $email (sort keys %Participants) { # later wins + $Event{replyTo} = { imip => "mailto:$email" } if grep { $_ eq 'owner' } @{$Participants{$email}{roles}}; + } + $Event{participants} = \%Participants if %Participants; + + # ============= Alerts + # useDefaultAlerts is not supported + $Event{alerts} = \%Alerts if %Alerts; + + if ($Properties{lastmodified}{value}) { + # UTC item + my $Date = eval { $Self->_getDateObj($Calendar, $Properties{lastmodified}, 'UTC') }; + $Event{lastModified} = $Date->iso8601() . 'Z'; + } + if ($Properties{'recurrence-id'}{value}) { + # in our system it's always in the timezone of the event, but iCloud + # returns it in UTC despite the event having a timezone. Super weird. + # Anyway, we need to format it to the StartTimeZone of the parent + # event if there is one, and we don't have that yet! + $Event{_recurrenceObj} = $Self->_getDateObj($Calendar, $Properties{'recurrence-id'}); + } + push @Events, \%Event; + } + } + + return \@Events; +} + +sub _getTimeZone { + my $Self = shift; + my ($Calendar, $Element) = @_; + + if ($Element->{value} =~ m/Z$/) { + return 'Etc/UTC'; + } + + my $TZID = $Element->{params}{tzid}[0]; + + return undef unless $TZID; + + return $Self->{_tznamemap}{$TZID} if exists $Self->{_tznamemap}{$TZID}; + + my %TzOffsets; + + foreach my $VTimeZone (@{$Calendar->{objects} || []}) { + next unless lc $VTimeZone->{type} eq 'vtimezone'; + next unless ($VTimeZone->{properties}{tzid}[0]{value} || '') eq $TZID; + + foreach my $Observance (@{$VTimeZone->{objects} || []}) { + next unless grep { (lc $Observance->{type} || '') eq $_ } qw{standard daylight}; + next unless defined $Observance->{properties}{tzoffsetto}[0]{value}; + + $TzOffsets{lc $Observance->{type}} + = $Observance->{properties}{tzoffsetto}[0]{value}; + } + } + + return undef unless exists $TzOffsets{standard}; + + my $TimeZone = Net::CalDAVTalk::TimeZones->GetTimeZone( + TZID => $TZID, + Time => $Element->{value}, + StandardTzOffsetTo => $TzOffsets{standard}, + ($TzOffsets{daylight} + ? (DaylightTzOffsetTo => $TzOffsets{daylight}) + : ()), + ) || undef; + + $Self->{_tznamemap}{$TZID} = $TimeZone; + return $TimeZone; +} + +sub _wireDate { + # format: YYYY-MM-DDTHH:MM:SS Z? + my $isoDate = shift; + my $timeZone = shift || $FLOATING; + confess "Invalid value '$isoDate' was not ISO8601" unless $isoDate =~ m/^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(Z?)$/i; + $timeZone = 'Etc/UTC' if $7; + + my $Date = DateTime->_new( + year => $1, + month => $2, + day => $3, + hour => $4, + minute => $5, + second => $6, + time_zone => $timeZone, + locale => $LOCALE, + ) or confess "Invalid value '$isoDate'"; + + return $Date; +} + +sub _vDate { + # format: :YYYYMMDDTHHMMSS (floating) + # format: :YYYYMMDDTHHMMSSZ (UTC) + # format: ;TZID=X/Y:YYMMDDTHHMMSS (zoned) + # format: ;TYPE=DATE:YYYYMMDD (but we don't know about that) + my $vDate = shift; + + if ($vDate =~ m/^(\d\d\d\d)(\d\d)(\d\d)T(\d\d)(\d\d)(\d\d)(\.\d+)?(Z?)$/i) { + my $Date = DateTime->_new( + year => $1, + month => $2, + day => $3, + hour => $4, + minute => $5, + second => $6, + # ignore milliseconds in $7 + time_zone => ($8 eq 'Z' ? $UTC : $FLOATING), + locale => $LOCALE, + ) or confess "Invalid value '$vDate' for DATETIME"; + + return ($Date, 1); + } + + if ($vDate =~ m/^(\d\d\d\d)(\d\d)(\d\d)$/) { + # all day + my $Date = DateTime->_new( + year => $1, + month => $2, + day => $3, + time_zone => $FLOATING, + locale => $LOCALE, + ) or confess "Invalid value '$vDate' for DATE"; + + return ($Date, 0); + } + + # we only support those two patterns + confess "Date '$vDate' was neither a DATE or DATETIME value"; +} + +sub _makeVTime { + my $Self = shift; + my ($TimeZones, $wire, $tz, $IsAllDay) = @_; + + my $date = _wireDate($wire, $tz); + + return $Self->_makeVTimeObj($TimeZones, $date, $tz, $IsAllDay); +} + +sub _makeVTimeObj { + my $Self = shift; + my ($TimeZones, $date, $tz, $IsAllDay) = @_; + + # all day? + if ($IsAllDay) { + return [$date->strftime('%Y%m%d'), { VALUE => 'DATE' }]; + } + + # floating? + unless ($tz) { + return [$date->strftime('%Y%m%dT%H%M%S')]; + } + + # UTC? + if ($UTCLinks{$tz}) { + return [$date->strftime('%Y%m%dT%H%M%SZ')]; + } + + my $zone = $Self->tz($tz); + + $TimeZones->{$zone->name()} = 1; + + return [$date->strftime('%Y%m%dT%H%M%S'), { TZID => $zone->name() }]; +} + +sub _makeZTime { + my ($Self, $date) = @_; + return $Self->_makeVTime({}, $date, 'UTC'); +} + +sub _makeLTime { + my $Self = shift; + my ($TimeZones, $ltime, $tz, $IsAllDay) = @_; + + my $date = _wireDate($ltime, $Self->tz($tz)); + + return [$date->strftime('%Y%m%d'), { VALUE => 'DATE' }] if $IsAllDay; + + unless ($tz) { + # floating + return [$date->strftime('%Y%m%dT%H%M%S')]; + } + + if ($tz =~ m/UTC/i) { + return [$date->strftime('%Y%m%dT%H%M%SZ')]; + } + + # XXX - factor this crap out + $TimeZones->{$tz} = 1; + + # XXX - use our cache + my $zone = $Self->tz($tz); + + return [$date->strftime('%Y%m%dT%H%M%S'), { TZID => $zone->name() }]; +} + +sub _argsToVEvents { + my $Self = shift; + my ($TimeZones, $Args, $recurrenceData) = @_; + my @VEvents; + + my $VEvent = Data::ICal::Entry::Event->new(); + + # required properties + $VEvent->add_properties( + uid => $Args->{uid}, + sequence => ($Args->{sequence} || 0), + transp => ($Args->{showAsFree} ? 'TRANSPARENT' : 'OPAQUE'), + ); + + if ($recurrenceData) { + my ($recurrenceId, $TopLevel) = @$recurrenceData; + $VEvent->add_property('recurrence-id' => $Self->_makeLTime($TimeZones, $recurrenceId, $TopLevel->{timeZone}, $TopLevel->{isAllDay})); + } + + # direct copy if properties exist + foreach my $Property (qw{description title}) { + my $Prop = $Args->{$Property} // ''; + next if $Prop eq ''; + my %lang; + $lang{language} = $Args->{locale} if exists $Args->{locale}; + my $key = $Property; + $key = 'summary' if $Property eq 'title'; + $VEvent->add_property($key => [$Prop, \%lang]); + } + + # dates in UTC - stored in UTC + $VEvent->add_property(created => $Self->_makeZTime($Args->{created})) if $Args->{created}; + $VEvent->add_property(dtstamp => $Self->_makeZTime($Args->{updated} || DateTime->now->iso8601())); + + # dates in localtime - zones based on location + my $EndTimeZone; + my $locations = $Args->{locations} || {}; + foreach my $id (sort keys %$locations) { + if ($locations->{$id}{rel} and $locations->{id}{rel} eq 'end') { + $EndTimeZone = $locations->{end}{timeZone}; + } + if ($locations->{$id}{name}) { + $VEvent->add_property(location => $locations->{$id}{name}); + } + } + + my $StartTimeZone = $Args->{timeZone}; + my $Start = _wireDate($Args->{start}, $StartTimeZone); + $VEvent->add_property(dtstart => $Self->_makeVTimeObj($TimeZones, $Start, $StartTimeZone, $Args->{isAllDay})); + if ($Args->{duration}) { + $EndTimeZone //= $StartTimeZone; + my $Duration = eval { DateTime::Format::ICal->parse_duration($Args->{duration}) }; + my $End = $Start->clone()->add($Duration) if $Duration; + $VEvent->add_property(dtend => $Self->_makeVTimeObj($TimeZones, $End, $EndTimeZone, $Args->{isAllDay})); + } + + if ($Args->{recurrenceRule}) { + my %Recurrence = $Self->_makeRecurrence($Args->{recurrenceRule}, $Args->{isAllDay}, $StartTimeZone); + + # RFC 2445 4.3.10 - FREQ is the first part of the RECUR value type. + # RFC 5545 3.3.10 - FREQ should be first to ensure backward compatibility. + my $rule = join(';', + ('FREQ=' . delete($Recurrence{FREQ})), + (map { "$_=$Recurrence{$_}" } keys %Recurrence), + ); + $VEvent->add_property(rrule => $rule); + } + + if ($Args->{recurrenceOverrides}) { + foreach my $recurrenceId (sort keys %{$Args->{recurrenceOverrides}}) { + my $val = $Args->{recurrenceOverrides}{$recurrenceId}; + if ($val) { + if (keys %$val) { + my $SubEvent = $Self->_maximise($Args, $val, $recurrenceId); + push @VEvents, $Self->_argsToVEvents($TimeZones, $SubEvent, [$recurrenceId, $Args]); + } + else { + $VEvent->add_property(rdate => $Self->_makeLTime($TimeZones, $recurrenceId, $StartTimeZone, $Args->{isAllDay})); + } + } + else { + $VEvent->add_property(exdate => $Self->_makeLTime($TimeZones, $recurrenceId, $StartTimeZone, $Args->{isAllDay})); + } + } + } + + if ($Args->{alerts}) { + for my $id (sort keys %{$Args->{alerts}}) { + my $Alert = $Args->{alerts}{$id}; + + my $Type = $Alert->{action}{type} // ''; + my $Recipients = $Alert->{action}{recipients} // []; + my $Uri = $Alert->{action}{uri} // ''; + my $Offset = $Alert->{offset}; + my $Sign = $Alert->{relativeTo} =~ m/before/ ? '-' : ''; + my $Loc1 = $Alert->{relativeTo} =~ m/end/ ? "ends" : "starts"; + my $Loc2 = $Alert->{relativeTo} =~ m/end/ ? "ended" : "started"; + my $Minutes = DateTime::Format::ICal->parse_duration(uc $Offset)->in_units('minutes'); + + my $VAlarm; + + if ($Type eq 'display') { + $VAlarm = Data::ICal::Entry::Alarm::Display->new(); + $VAlarm->add_properties( + description => (($Sign eq '-') + ? "'$Args->{title}' $Loc1 in $Minutes minutes" + : "'$Args->{title}' $Loc2 $Minutes minutes ago"), + ); + } + elsif ($Type eq 'email' || $Type eq 'uri') { + my ($Summary, $Description); + + if ($Sign eq '-') { + $Summary = "Event alert: '$Args->{title}' $Loc1 in $Minutes minutes"; + $Description = "Your event '$Args->{title}' $Loc1 in $Minutes minutes"; + } + else { + $Summary = "Event alert: '$Args->{title}' $Loc2 $Minutes minutes ago"; + $Description = "Your event '$Args->{title}' $Loc2 $Minutes minutes ago"; + } + + $VAlarm = Data::ICal::Entry::Alarm::Email->new(); + $VAlarm->add_properties( + summary => $Summary, + description => join("\n", + $Description, + "", + "Description:", + $Args->{description}, + # XXX more + ), + (map { ( attendee => "MAILTO:$_" ) } @$Recipients), # XXX naive? + ); + + if ($Type eq 'uri') { + $VAlarm->add_property("X-URI", $Uri); + } + } + else { + confess "Unknown alarm type $Type"; + } + + $VAlarm->add_property(uid => $id); + $VAlarm->add_property(trigger => "${Sign}$Offset"); + $VAlarm->add_property(related => 'end') if $Alert->{relativeTo} =~ m/end/; + + if ($Alert->{action}{acknowledged}) { + $VAlarm->add_property(acknowledged => $Self->_makeZTime($Alert->{action}{acknowledged})); + } + + $VEvent->add_entry($VAlarm); + } + } + + my %namemap; + if ($Args->{participants}) { + foreach my $Address (sort keys %{$Args->{participants}}) { + my $Attendee = $Args->{participants}{$Address}; + my $Email = $Attendee->{email} || $Address; + my $Rsvp = $Attendee->{rsvp}; + + my %AttendeeProps; + if ($Attendee->{"name"}) { + $AttendeeProps{"CN"} = $Attendee->{"name"}; + $namemap{lc "mailto:$Email"}= $Attendee->{"name"}; + } + + next unless grep { $_ eq 'attendee' } @{$Attendee->{roles}}; + + $AttendeeProps{"CUTYPE"} = uc $Attendee->{"kind"} if defined $Attendee->{"kind"}; + $AttendeeProps{"RSVP"} = uc $Attendee->{"scheduleRSVP"} if defined $Attendee->{"scheduleRSVP"}; + $AttendeeProps{"X-SEQUENCE"} = $Attendee->{"x-sequence"} if defined $Attendee->{"x-sequence"}; + $AttendeeProps{"X-DTSTAMP"} = $Self->_makeZTime($Attendee->{"scheduleUpdated"}) if defined $Attendee->{"scheduleUpdated"}; + foreach my $prop (keys %AttendeeProps) { + delete $AttendeeProps{$prop} if $AttendeeProps{$prop} eq ''; + } + if (grep { $_ eq 'chair' } @{$Attendee->{roles}}) { + $Attendee->{ROLE} = 'CHAIR'; + } + elsif ($Attendee->{schedulePriority} and $Attendee->{schedulePriority} eq 'optional') { + $Attendee->{ROLE} = 'OPT-PARTICIPANT'; + } + elsif ($Attendee->{schedulePriority} and $Attendee->{schedulePriority} eq 'non-participant') { + $Attendee->{ROLE} = 'NON-PARTICIPANT'; + } + # default is REQ-PARTICIPANT + + $AttendeeProps{PARTSTAT} = uc $Attendee->{"scheduleStatus"} if $Attendee->{"scheduleStatus"}; + + $VEvent->add_property(attendee => [ "MAILTO:$Email", \%AttendeeProps ]); + } + } + if ($Args->{replyTo}) { + if ($Args->{replyTo}{imip}) { + my $CN = $namemap{lc $Args->{replyTo}{imip}}; + $VEvent->add_property(organizer => [ $Args->{replyTo}{imip}, $CN ? {CN => $CN} : () ]); + } + } + + if ($Args->{links}) { + foreach my $uri (sort keys %{$Args->{links}}) { + my $Attach = $Args->{links}{$uri}; + my $Url = $Attach->{href} || $uri; + if ($Attach->{rel} && $Attach->{rel} eq 'enclosure') { + my $FileName = $Attach->{title}; + my $Mime = $Attach->{type}; + my $Size = $Attach->{size}; + + my %AttachProps; + $AttachProps{FMTTYPE} = $Mime if defined $Mime; + $AttachProps{SIZE} = $Size if defined $Size; + $AttachProps{FILENAME} = $FileName if defined $FileName; + $VEvent->add_property(attach => [ $Url, \%AttachProps ]); + } + # otherwise it's just a URL + else { + $VEvent->add_property(url => [ $Url ]); + } + } + } + + # detect if this is a dummy top-level event and skip it + unshift @VEvents, $VEvent unless ($Args->{replyTo} and not $Args->{participants}); + + return @VEvents; +} + +sub _argsToVCalendar { + my $Self = shift; + my $Item = shift; + my %ExtraProp = @_; + + my $VCalendar = Data::ICal->new(); + my $havepid = 0; + + foreach my $extra (keys %ExtraProp) { + $VCalendar->add_properties($extra => $ExtraProp{$extra}); + } + $VCalendar->add_properties(calscale => 'GREGORIAN'); + + my @VEvents; + my %TimeZones; + foreach my $Args (ref $Item eq 'ARRAY' ? @$Item : $Item) { + if (not $havepid and $Args->{prodId}) { + $VCalendar->add_properties('prodid' => $Args->{prodId}); + $havepid = 1; + } + # initialise timestamp if not given one + $Args->{dtstamp} //= DateTime->now()->strftime('%Y-%m-%dT%H:%M:%S'); + push @VEvents, $Self->_argsToVEvents(\%TimeZones, $Args); + } + + # add timezone parts first + foreach my $Zone (sort keys %TimeZones) { + my $VTimeZone = Net::CalDAVTalk::TimeZones->GetVTimeZone($Zone); + next unless $VTimeZone; + $VCalendar->add_entry($VTimeZone); + } + + # then the events + foreach my $VEvent (@VEvents) { + $VCalendar->add_entry($VEvent); + } + + return $VCalendar; +} + +sub _makeRecurrence { + my $Self = shift; + my ($Args, $IsAllDay, $TZ) = @_; + + my %Recurrence; + + # validate simple recurrence properties {{{ + + unless (ref($Args) eq 'HASH') { + confess 'Invalid recurrence'; + } + + if ($Args->{frequency}) { + unless (grep { $_ eq $Args->{frequency} } @Frequencies) { + confess "Invalid recurrence frequency ($Args->{frequency})"; + } + + $Recurrence{FREQ} = uc($Args->{frequency}); + } + else { + confess 'Recurrence frequency not specified'; + } + + if (defined $Args->{interval}) { + unless ($Args->{interval} =~ /^\d+$/) { + confess "Invalid recurrence interval ($Args->{interval})"; + } + + if ($Args->{interval} == 0) { + confess "Recurrence interval is out of range ($Args->{interval})"; + } + + if ($Args->{interval} > 1) { + $Recurrence{INTERVAL} = $Args->{interval}; + } + } + + if (defined $Args->{firstDayOfWeek}) { + unless (exists $DaysByIndex{$Args->{firstDayOfWeek}}) { + confess "Invalid recurrence firstDayOfWeek ($Args->{firstDayOfWeek})"; + } + + unless ($Args->{firstDayOfWeek} == 1){ + $Recurrence{WKST} = uc $DaysByIndex{$Args->{firstDayOfWeek}}; + } + } + + if ($Args->{byDay}) { + unless (ref($Args->{byDay}) eq 'ARRAY') { + confess 'Invalid recurrence byDay'; + } + + unless (@{$Args->{byDay}}) { + confess 'Recurrence byDay is empty'; + } + + $Recurrence{BYDAY} = join(',', map{ _byDay2BYDAY($_) } @{$Args->{byDay}}); + } + + if ($Args->{byMonth}) { + unless (ref($Args->{byMonth}) eq 'ARRAY') { + confess 'Invalid recurrence byMonth'; + } + + unless (@{$Args->{byMonth}}) { + confess 'Recurrence byMonth is empty'; + } + + my @BYMONTHS; + + foreach my $byMonth (@{$Args->{byMonth}}) { + unless ($byMonth =~ /^(\d+)L?$/i) { + confess "Recurrence byMonth is not a number with optional L ($byMonth)"; + } + my $monthNum = $1; + unless ($monthNum >= 1 and $monthNum <= 13) { + # not sure if 13 is OK + confess "Recurrence byMonth is too high ($monthNum)"; + } + + push @BYMONTHS, $byMonth; + } + + $Recurrence{BYMONTH} = join ',', @BYMONTHS; + } + + if (defined $Args->{count}) { + if (defined $Args->{until}) { + confess 'Recurrence count and until cannot both be set'; + } + + unless ($Args->{count} =~ /^\d+$/) { + confess "Invalid recurrence count ($Args->{count})"; + } + + $Recurrence{COUNT} = $Args->{count}; + } + + if ($Args->{until}) { + my $Until = _wireDate($Args->{until}, $Self->tz($TZ)); + + if ($IsAllDay) { + $Recurrence{UNTIL} = $Until->strftime('%Y%m%d'); + } + else { + # API is in Localtime, but both iCloud and Google use 'Z' times as per + # rfc2445, so we'll copy them for compatibility. + $Until->set_time_zone($UTC); + $Recurrence{UNTIL} = $Until->strftime('%Y%m%dT%H%M%SZ'); + } + } + + # }}} + + # validate generic recurrence properties {{{ + + foreach my $Property (keys %RecurrenceProperties) { + my $Name = $RecurrenceProperties{$Property}{name}; + + if ($Args->{$Name}) { + unless (ref($Args->{$Name}) eq 'ARRAY') { + confess "Invalid recurrence $Name"; + } + + unless (@{$Args->{$Name}}) { + confess "Recurrence $Name is empty"; + } + + my @Values; + + foreach my $Value (@{$Args->{$Name}}) { + my ($Valid, $Min) = $RecurrenceProperties{$Property}{signed} + ? ('[-+]?[1-9]\d*', ($RecurrenceProperties{$Property}{max} * -1)) + : ('\d+', 0); + + unless ($Value =~ /^$Valid$/) { + confess "Invalid recurrence $Name ($Value)"; + } + + unless (($Min <= $Value) and ($Value <= $RecurrenceProperties{$Property}{max})) { + confess "Recurrence $Name is out of range ($Value)"; + } + + push @Values, $Value; + } + + $Recurrence{uc $Property} = join ',', @Values; + } + } + + # }}} + + return %Recurrence; +} + +=head2 $self->vcalendarToEvents($Data) + +Convert a text vcalendar (either a single event or an entire ical file) into an array of events. + +Returns an array (not arrayref) of Events in UID order. + +e.g. + + foreach my $Event ($CalDAV->vcalendarToEvents($Data)) { + # ... + } + +=cut + +sub _insert_override { + my $Event = shift; + my $recurrenceId = shift; + my $Recurrence = shift; + + my %override; + my %oldkeys = map { $_ => 1 } keys %$Event; + foreach my $Key (sort keys %$Recurrence) { + delete $oldkeys{$Key}; + next if $MustBeTopLevel{$Key}; # XXX - check safeeq and die? + if ($Key eq 'start') { + # special case, it's the recurrence-id + next if _safeeq($Recurrence->{start}, $recurrenceId); + $override{start} = $Recurrence->{start}; + next; + } + next if _safeeq($Recurrence->{$Key}, $Event->{$Key}); + _add_override(\%override, _quotekey($Key), $Recurrence->{$Key}, $Event->{$Key}); + } + + foreach my $Key (sort keys %oldkeys) { + next if $MustBeTopLevel{$Key}; + $override{$Key} = $JSON::null; + } + + # in theory should never happen, but you could edit something back to be identical + return unless %override; + $Event->{recurrenceOverrides}{$recurrenceId} = \%override; +} + +sub vcalendarToEvents { + my $Self = shift; + my $Data = shift; + + # Internal caches need to be invalidated on each item read! A bit evil really... + delete $Self->{_tznamemap}; + + my %map; + my %exceptions; + my $Events = $Self->_getEventsFromVCalendar($Data); + + foreach my $Event (@$Events) { + my $uid = $Event->{uid}; + if ($Event->{_recurrenceObj}) { + push @{$exceptions{$uid}}, $Event; + } + elsif ($map{$uid}) { + # it looks like sometimes Google doesn't remember to put the Recurrence ID + # on additional recurrences after the first one, which is going to screw up + # pretty badly because if the date has changed, then we can't even notice + # which recurrent it was SUPPOSED to be. *sigh*. + warn "DUPLICATE EVENT FOR $uid\n" . Dumper($map{$uid}, $Event); + push @{$exceptions{$uid}}, $Event; + $map{$uid}{_dirty} = 1; + } + else { + $map{$uid} = $Event; + } + } + + foreach my $uid (keys %exceptions) { + unless ($map{$uid}) { + # create a synthetic top-level + my $First = $exceptions{$uid}[0]; + $map{$uid} = { + uid => $uid, + # these two are required at top level, but may be different + # in recurrences so aren't in MustBeTopLevel + start => $First->{start}, + updated => $First->{updated}, + }; + $map{$uid}{timeZone} = $First->{timeZone} unless $First->{isAllDay}; + foreach my $key (keys %MustBeTopLevel) { + $map{$uid}{$key} = $First->{$key} if exists $First->{$key}; + } + } + foreach my $SubEvent (@{$exceptions{$uid}}) { + my $recurrenceId = $SubEvent->{start}; + if ($SubEvent->{_recurrenceObj}) { + my $Date = delete $SubEvent->{_recurrenceObj}; + $Date->set_time_zone($map{$uid}{timeZone}) if $map{$uid}{timeZone}; + $recurrenceId = $Date->iso8601(); + } + _insert_override($map{$uid}, $recurrenceId, $SubEvent); + } + } + + return map { $map{$_} } sort keys %map; +} + +=head2 $self->UpdateAddressSet($DisplayName, $EmailAddress) + +Set the address set and display name for the calendar user (if supported) + +=cut + +sub UpdateAddressSet { + my ($Self, $NewDisplayName, $NewAddressSet) = @_; + + my ($DisplayName, $AddressSet) = $Self->GetProps(\$Self->{principal}, 'D:displayname', [ 'C:calendar-user-address-set', 'D:href' ]); + + if (!$AddressSet || $AddressSet ne "mailto:" . $NewAddressSet || + !$DisplayName || $DisplayName ne $NewDisplayName) { + $Self->Request( + 'PROPPATCH', + "", + x('D:propertyupdate', $Self->NS(), + x('D:set', + x('D:prop', + x('D:displayname', $NewDisplayName), + x('C:calendar-user-address-set', "mailto:" . $NewAddressSet), + ) + ) + ) + ); + return 1; + } + + return 0; +} + +=head2 $self->GetICal($calendarId, $isFreeBusy) + +Given a calender, fetch all the events and generate an ical format file +suitable for import into a client. + +=cut + +sub GetICal { + my $Self = shift; + my $calendarId = shift; + my $isFreeBusy = shift; + + confess "Need a calendarId" unless $calendarId; + + my $Calendars = $Self->GetCalendars(); + foreach my $Cal (@$Calendars) { + next unless $calendarId eq $Cal->{id}; + my ($Events, $Errors) = $isFreeBusy ? + $Self->GetFreeBusy($calendarId) : + $Self->GetEvents($calendarId); + return undef if @$Errors; + $Self->_stripNonICal($_) for @$Events; + my $VCalendar = $Self->_argsToVCalendar($Events, + method => 'PUBLISH', + 'x-wr-calname' => $Cal->{name}, + 'x-wr-timezone' => $Cal->{timeZone}, + 'x-apple-calendar-color' => $Cal->{color}, + # XXX - do we want to add our sync-token here or something? + ); + return ($VCalendar->as_string(), $Cal); + } + return undef; # 404 +} + +sub _quotekey { + my $key = shift; + $key =~ s/\~/~0/gs; + $key =~ s/\//~1/gs; + return $key; +} + +sub _unquotekey { + my $key = shift; + $key =~ s/\~1/\//gs; + $key =~ s/\~0/~/gs; + return $key; +} + +sub _add_override { + my ($override, $prefix, $New, $Old) = @_; + + # basic case - it's not an object, so we just override + if ($ENV{JMAP_ALWAYS_FULL} or ref($New) ne 'HASH' or ref($Old) or 'HASH') { + $override->{$prefix} = $New; + return; + } + + # XXX - if too many, we could just abort... + my %subover; + my %oldkeys = map { $_ => 1 } keys %$Old; + foreach my $Key (sort keys %$New) { + delete $oldkeys{$Key}; + next if _safeeq($New->{$Key}, $Old->{$Key}); + _add_override(\%subover, "$prefix/" . _quotekey($Key), $New->{$Key}, $Old->{$Key}); + } + foreach my $Key (sort keys %oldkeys) { + $subover{"$prefix/" . _quotekey($Key)} = $JSON::null; + } + + # which one is better? + if (length(encode_json($New)) < length(encode_json(\%subover))) { + $override->{$prefix} = $New; # cheaper to just encode the whole object + } + else { + $override->{$_} = $subover{$_} for keys %subover; + } +} + +sub _apply_patch { + my $path = shift; + my $hash = shift; + my $value = shift; + + return unless $path =~ s{^([^/]+)(/?)}{}; + return unless ref($hash) eq 'HASH'; + my $qkey = $1; + my $slash = $2; + my $key = _unquotekey($qkey); + if ($slash) { + _apply_patch($path, $hash->{$key}, $value); + } + elsif(defined $value) { + $hash->{$key} = $value; + } + else { + delete $hash->{$key}; + } +} + +sub _maximise { + my $Self = shift; + my $Event = shift; + my $Recurrence = shift; + my $recurrenceId = shift; + + #warn "MAXIMIZING EVENT INTO RECURRENCE: " . Dumper($Event, $Recurrence); + + my $new = _deepcopy($Event); + $new->{start} = $recurrenceId; + delete $new->{recurrenceRule}; + delete $new->{recurrenceOverrides}; + + foreach my $path (sort keys %$Recurrence) { + my $value = $Recurrence->{$path}; + _apply_patch($path, $new, $value); + } + + return $new; +} + +sub _stripNonICal { + my $Self = shift; + my $Event = shift; + + delete $Event->{alerts}; + delete $Event->{attendees}; + delete $Event->{organizer}; + + foreach my $exception (values %{$Event->{exceptions}}) { + next unless $exception; + $Self->_stripNonICal($exception); + } +} + +sub _safeeq { + my ($a, $b) = @_; + my $json = JSON::XS->new->canonical; + return $json->encode([$a]) eq $json->encode([$b]); +} + +sub _deepcopy { + my $data = shift; + my $json = JSON::XS->new->canonical; + my $enc = $json->encode([$data]); + my $copy = $json->decode($enc); + return $copy->[0]; +} + + +=head1 AUTHOR + +Bron Gondwana, C<< >> + +=head1 BUGS + +Please report any bugs or feature requests to C, or through +the web interface at L. I will be notified, and then you'll +automatically be notified of progress on your bug as I make changes. + + + + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc Net::CalDAVTalk + + +You can also look for information at: + +=over 4 + +=item * RT: CPAN's request tracker (report bugs here) + +L + +=item * AnnoCPAN: Annotated CPAN documentation + +L + +=item * CPAN Ratings + +L + +=item * Search CPAN + +L + +=back + + +=head1 ACKNOWLEDGEMENTS + + +=head1 LICENSE AND COPYRIGHT + +Copyright 2015 FastMail Pty Ltd. + +This program is free software; you can redistribute it and/or modify it +under the terms of the the Artistic License (2.0). You may obtain a +copy of the full license at: + +L + +Any use, modification, and distribution of the Standard or Modified +Versions is governed by this Artistic License. By using, modifying or +distributing the Package, you accept this license. Do not use, modify, +or distribute the Package, if you do not accept this license. + +If your Modified Version has been derived from a Modified Version made +by someone other than you, you are nevertheless required to ensure that +your Modified Version complies with the requirements of this license. + +This license does not grant you the right to use any trademark, service +mark, tradename, or logo of the Copyright Holder. + +This license includes the non-exclusive, worldwide, free-of-charge +patent license to make, have made, use, offer to sell, sell, import and +otherwise transfer the Package with respect to any patent claims +licensable by the Copyright Holder that are necessarily infringed by the +Package. If you institute patent litigation (including a cross-claim or +counterclaim) against any party alleging that the Package constitutes +direct or contributory patent infringement, then this Artistic License +to you shall terminate on the date that such litigation is filed. + +Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER +AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. +THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY +YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR +CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR +CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +=cut + +1; # End of Net::CalDAVTalk diff --git a/lib/Net/CalDAVTalk/TimeZones.pm b/lib/Net/CalDAVTalk/TimeZones.pm new file mode 100644 index 0000000..42ca4f5 --- /dev/null +++ b/lib/Net/CalDAVTalk/TimeZones.pm @@ -0,0 +1,13935 @@ +package Net::CalDAVTalk::TimeZones; + +=head1 NAME + +Net::CalDAVTalk::TimeZone - autogenerated timezone data for Net::CalDAVTalk + +=head1 SYNOPSIS + + *** WARNING: DO NOT EDIT *** + + This file is generated by utils/GenerateTimeZoneModule.pl + + ./utils/GenerateTimeZoneModule.pl htdocs/ajaxui/build/fastmail/timezones-raw.js > modules/Net/CalDAVTalk/TimeZones.pm + + Generated: Thu Aug 13 02:55:03 2015 + +=cut + +use strict; +use warnings; + +use Data::ICal::Entry::TimeZone; +use Data::ICal::Entry::TimeZone::Daylight; +use Data::ICal::Entry::TimeZone::Standard; +use Data::ICal::TimeZone; +use DateTime::Format::ISO8601; +use DateTime::TimeZone; +use Text::LevenshteinXS qw{distance}; + +our $RulesByZone = { + 'America/Bogota' => { + 'StandardTzOffset' => '-0500' + }, + 'America/Whitehorse' => { + 'StandardTzOffset' => '-0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0700', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Africa/Kinshasa' => { + 'StandardTzOffset' => '+0100' + }, + 'Antarctica/Palmer' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=4SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=1SU' + }, + 'America/Mazatlan' => { + 'StandardTzOffset' => '-0700', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '-0600', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU' + }, + 'America/Indiana/Vincennes' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Africa/Conakry' => { + 'StandardTzOffset' => '+0000' + }, + 'Asia/Manila' => { + 'StandardTzOffset' => '+0800' + }, + 'America/Nassau' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Europe/Belgrade' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Asia/Dhaka' => { + 'StandardTzOffset' => '+0600' + }, + 'Etc/GMT+2' => { + 'StandardTzOffset' => '+0200' + }, + 'America/Los_Angeles' => { + 'StandardTzOffset' => '-0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0700', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Aqtau' => { + 'StandardTzOffset' => '+0500' + }, + 'Asia/Dushanbe' => { + 'StandardTzOffset' => '+0500' + }, + 'Africa/Bujumbura' => { + 'StandardTzOffset' => '+0200' + }, + 'Asia/Baghdad' => { + 'StandardTzOffset' => '+0300', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYMONTHDAY=1', + 'DaylightTzOffset' => '+0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYMONTHDAY=1' + }, + 'Asia/Beirut' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Juneau' => { + 'StandardTzOffset' => '-0900', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0800', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Etc/GMT+10' => { + 'StandardTzOffset' => '+1000' + }, + 'America/Inuvik' => { + 'StandardTzOffset' => '-0700', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0600', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Pyongyang' => { + 'StandardTzOffset' => '+0900' + }, + 'Africa/Nairobi' => { + 'StandardTzOffset' => '+0300' + }, + 'Pacific/Norfolk' => { + 'StandardTzOffset' => '+1130' + }, + 'America/St_Johns' => { + 'StandardTzOffset' => '-0330', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0230', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Pacific/Guam' => { + 'StandardTzOffset' => '+1000' + }, + 'Australia/Currie' => { + 'StandardTzOffset' => '+1000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU', + 'DaylightTzOffset' => '+1100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=1SU' + }, + 'America/Hermosillo' => { + 'StandardTzOffset' => '-0700' + }, + 'Asia/Muscat' => { + 'StandardTzOffset' => '+0400' + }, + 'America/Indiana/Knox' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Bahrain' => { + 'StandardTzOffset' => '+0300' + }, + 'Asia/Samarkand' => { + 'StandardTzOffset' => '+0500' + }, + 'Africa/Addis_Ababa' => { + 'StandardTzOffset' => '+0300' + }, + 'America/Halifax' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Ulaanbaatar' => { + 'StandardTzOffset' => '+0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=-1SA', + 'DaylightTzOffset' => '+0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SA' + }, + 'Asia/Jerusalem' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=8FR' + }, + 'America/Indiana/Vevay' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Cayman' => { + 'StandardTzOffset' => '-0500' + }, + 'America/Guyana' => { + 'StandardTzOffset' => '-0400' + }, + 'Europe/Chisinau' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Etc/GMT+14' => { + 'StandardTzOffset' => '+1400' + }, + 'Asia/Kuwait' => { + 'StandardTzOffset' => '+0300' + }, + 'Atlantic/Reykjavik' => { + 'StandardTzOffset' => '+0000' + }, + 'Europe/Bucharest' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Asia/Krasnoyarsk' => { + 'StandardTzOffset' => '+0800' + }, + 'Pacific/Wake' => { + 'StandardTzOffset' => '+1200' + }, + 'Africa/Blantyre' => { + 'StandardTzOffset' => '+0200' + }, + 'Pacific/Tahiti' => { + 'StandardTzOffset' => '-1000' + }, + 'America/Dawson_Creek' => { + 'StandardTzOffset' => '-0700' + }, + 'America/North_Dakota/New_Salem' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Europe/Istanbul' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Pacific/Fiji' => { + 'StandardTzOffset' => '+1200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=1;BYDAY=3SU', + 'DaylightTzOffset' => '+1300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=4SU' + }, + 'America/Atikokan' => { + 'StandardTzOffset' => '-0500' + }, + 'Pacific/Marquesas' => { + 'StandardTzOffset' => '-0930' + }, + 'America/Bahia' => { + 'StandardTzOffset' => '-0300' + }, + 'America/Matamoros' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Australia/Broken_Hill' => { + 'StandardTzOffset' => '+0930', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU', + 'DaylightTzOffset' => '+1030', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=1SU' + }, + 'America/Antigua' => { + 'StandardTzOffset' => '-0400' + }, + 'America/New_York' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Pacific/Pohnpei' => { + 'StandardTzOffset' => '+1100' + }, + 'America/El_Salvador' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=5;BYDAY=1SU' + }, + 'America/Blanc-Sablon' => { + 'StandardTzOffset' => '-0400' + }, + 'Africa/Harare' => { + 'StandardTzOffset' => '+0200' + }, + 'Asia/Shanghai' => { + 'StandardTzOffset' => '+0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=3SU', + 'DaylightTzOffset' => '+0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=3SU' + }, + 'Indian/Comoro' => { + 'StandardTzOffset' => '+0300' + }, + 'Africa/Porto-Novo' => { + 'StandardTzOffset' => '+0100' + }, + 'Pacific/Nauru' => { + 'StandardTzOffset' => '+1200' + }, + 'Europe/Warsaw' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Etc/GMT+6' => { + 'StandardTzOffset' => '+0600' + }, + 'Europe/Brussels' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Havana' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Antarctica/Casey' => { + 'StandardTzOffset' => '+0800' + }, + 'America/Barbados' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=1SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=3SU' + }, + 'Pacific/Kwajalein' => { + 'StandardTzOffset' => '+1200' + }, + 'Africa/Ouagadougou' => { + 'StandardTzOffset' => '+0000' + }, + 'Africa/Abidjan' => { + 'StandardTzOffset' => '+0000' + }, + 'Asia/Hebron' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=4FR', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1TH' + }, + 'Etc/GMT-11' => { + 'StandardTzOffset' => '-1100' + }, + 'America/Rainy_River' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Makassar' => { + 'StandardTzOffset' => '+0800' + }, + 'Asia/Vladivostok' => { + 'StandardTzOffset' => '+1100' + }, + 'America/Santarem' => { + 'StandardTzOffset' => '-0300' + }, + 'Asia/Pontianak' => { + 'StandardTzOffset' => '+0700' + }, + 'Etc/GMT+11' => { + 'StandardTzOffset' => '+1100' + }, + 'Africa/Lusaka' => { + 'StandardTzOffset' => '+0200' + }, + 'Africa/Luanda' => { + 'StandardTzOffset' => '+0100' + }, + 'America/Argentina/Mendoza' => { + 'StandardTzOffset' => '-0300' + }, + 'Europe/Kaliningrad' => { + 'StandardTzOffset' => '+0300' + }, + 'Europe/Madrid' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Africa/Mogadishu' => { + 'StandardTzOffset' => '+0300' + }, + 'America/Yellowknife' => { + 'StandardTzOffset' => '-0700', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0600', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Atlantic/Stanley' => { + 'StandardTzOffset' => '-0300' + }, + 'Pacific/Majuro' => { + 'StandardTzOffset' => '+1200' + }, + 'America/Jamaica' => { + 'StandardTzOffset' => '-0500' + }, + 'Asia/Kashgar' => { + 'StandardTzOffset' => '+0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=3SU', + 'DaylightTzOffset' => '+0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=3SU' + }, + 'America/Argentina/Cordoba' => { + 'StandardTzOffset' => '-0300', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=3SU', + 'DaylightTzOffset' => '-0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=3SU' + }, + 'Indian/Antananarivo' => { + 'StandardTzOffset' => '+0300' + }, + 'Asia/Anadyr' => { + 'StandardTzOffset' => '+1200' + }, + 'Indian/Mauritius' => { + 'StandardTzOffset' => '+0400' + }, + 'Asia/Irkutsk' => { + 'StandardTzOffset' => '+0900' + }, + 'America/Cuiaba' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=2;BYDAY=3SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=3SU' + }, + 'Asia/Sakhalin' => { + 'StandardTzOffset' => '+1100' + }, + 'Africa/Sao_Tome' => { + 'StandardTzOffset' => '+0000' + }, + 'Pacific/Niue' => { + 'StandardTzOffset' => '-1100' + }, + 'America/Manaus' => { + 'StandardTzOffset' => '-0400' + }, + 'Etc/GMT+3' => { + 'StandardTzOffset' => '+0300' + }, + 'Africa/Monrovia' => { + 'StandardTzOffset' => '+0000' + }, + 'America/Tijuana' => { + 'StandardTzOffset' => '-0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0700', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Ho_Chi_Minh' => { + 'StandardTzOffset' => '+0700' + }, + 'Etc/GMT-3' => { + 'StandardTzOffset' => '-0300' + }, + 'Africa/Algiers' => { + 'StandardTzOffset' => '+0100' + }, + 'Europe/Riga' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Europe/Vilnius' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Asia/Colombo' => { + 'StandardTzOffset' => '+0530' + }, + 'Antarctica/DumontDUrville' => { + 'StandardTzOffset' => '+1000' + }, + 'America/Boise' => { + 'StandardTzOffset' => '-0700', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0600', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Pacific/Pago_Pago' => { + 'StandardTzOffset' => '-1100' + }, + 'Africa/Kampala' => { + 'StandardTzOffset' => '+0300' + }, + 'Indian/Christmas' => { + 'StandardTzOffset' => '+0700' + }, + 'Asia/Dubai' => { + 'StandardTzOffset' => '+0400' + }, + 'America/Dawson' => { + 'StandardTzOffset' => '-0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0700', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Pacific/Kiritimati' => { + 'StandardTzOffset' => '+1400' + }, + 'America/Bahia_Banderas' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU' + }, + 'America/Yakutat' => { + 'StandardTzOffset' => '-0900', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0800', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Kabul' => { + 'StandardTzOffset' => '+0430' + }, + 'America/Danmarkshavn' => { + 'StandardTzOffset' => '+0000' + }, + 'Etc/GMT-12' => { + 'StandardTzOffset' => '-1200' + }, + 'Europe/Uzhgorod' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Glace_Bay' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Africa/Bissau' => { + 'StandardTzOffset' => '+0000' + }, + 'America/Kentucky/Louisville' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Etc/GMT+5' => { + 'StandardTzOffset' => '+0500' + }, + 'Africa/Dar_es_Salaam' => { + 'StandardTzOffset' => '+0300' + }, + 'Africa/El_Aaiun' => { + 'StandardTzOffset' => '+0000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Etc/GMT+7' => { + 'StandardTzOffset' => '+0700' + }, + 'Asia/Amman' => { + 'StandardTzOffset' => '+0300' + }, + 'America/La_Paz' => { + 'StandardTzOffset' => '-0400' + }, + 'America/Costa_Rica' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=6;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=1;BYDAY=3SA' + }, + 'Pacific/Tongatapu' => { + 'StandardTzOffset' => '+1300', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=1;BYDAY=-1SU', + 'DaylightTzOffset' => '+1400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU' + }, + 'Etc/UCT' => { + 'StandardTzOffset' => '+0000' + }, + 'America/Nipigon' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Africa/Tunis' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Asia/Tbilisi' => { + 'StandardTzOffset' => '+0400' + }, + 'Europe/Simferopol' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Pacific/Guadalcanal' => { + 'StandardTzOffset' => '+1100' + }, + 'America/Regina' => { + 'StandardTzOffset' => '-0600' + }, + 'Pacific/Enderbury' => { + 'StandardTzOffset' => '+1300' + }, + 'Indian/Cocos' => { + 'StandardTzOffset' => '+0630' + }, + 'Australia/Perth' => { + 'StandardTzOffset' => '+0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU', + 'DaylightTzOffset' => '+0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' + }, + 'America/Creston' => { + 'StandardTzOffset' => '-0700' + }, + 'Etc/GMT-1' => { + 'StandardTzOffset' => '-0100' + }, + 'Asia/Kolkata' => { + 'StandardTzOffset' => '+0530' + }, + 'America/Argentina/Rio_Gallegos' => { + 'StandardTzOffset' => '-0300' + }, + 'America/Porto_Velho' => { + 'StandardTzOffset' => '-0400' + }, + 'Asia/Phnom_Penh' => { + 'StandardTzOffset' => '+0700' + }, + 'Asia/Magadan' => { + 'StandardTzOffset' => '+1200' + }, + 'Atlantic/Canary' => { + 'StandardTzOffset' => '+0000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Kentucky/Monticello' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Pacific/Chuuk' => { + 'StandardTzOffset' => '+1000' + }, + 'America/Swift_Current' => { + 'StandardTzOffset' => '-0600' + }, + 'Europe/Minsk' => { + 'StandardTzOffset' => '+0300' + }, + 'Pacific/Palau' => { + 'StandardTzOffset' => '+0900' + }, + 'Europe/Helsinki' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Australia/Melbourne' => { + 'StandardTzOffset' => '+1000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU', + 'DaylightTzOffset' => '+1100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=1SU' + }, + 'Etc/GMT+1' => { + 'StandardTzOffset' => '+0100' + }, + 'America/Monterrey' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU' + }, + 'America/Menominee' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Cayenne' => { + 'StandardTzOffset' => '-0300' + }, + 'Etc/GMT-2' => { + 'StandardTzOffset' => '-0200' + }, + 'America/Miquelon' => { + 'StandardTzOffset' => '-0300', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Iqaluit' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Etc/GMT-6' => { + 'StandardTzOffset' => '-0600' + }, + 'Etc/GMT' => { + 'StandardTzOffset' => '+0000' + }, + 'Asia/Novosibirsk' => { + 'StandardTzOffset' => '+0700' + }, + 'Australia/Adelaide' => { + 'StandardTzOffset' => '+0930', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU', + 'DaylightTzOffset' => '+1030', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=1SU' + }, + 'Europe/Amsterdam' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Europe/Moscow' => { + 'StandardTzOffset' => '+0400' + }, + 'Pacific/Rarotonga' => { + 'StandardTzOffset' => -1000, + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=1SU', + 'DaylightTzOffset' => '-0930', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' + }, + 'Europe/Malta' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Africa/Banjul' => { + 'StandardTzOffset' => '+0000' + }, + 'Africa/Tripoli' => { + 'StandardTzOffset' => '+0200' + }, + 'Indian/Kerguelen' => { + 'StandardTzOffset' => '+0500' + }, + 'Asia/Urumqi' => { + 'StandardTzOffset' => '+0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=3SU', + 'DaylightTzOffset' => '+0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=3SU' + }, + 'Africa/Libreville' => { + 'StandardTzOffset' => '+0100' + }, + 'Africa/Khartoum' => { + 'StandardTzOffset' => '+0300' + }, + 'America/Recife' => { + 'StandardTzOffset' => '-0300' + }, + 'America/Argentina/La_Rioja' => { + 'StandardTzOffset' => '-0300' + }, + 'Europe/Paris' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Indian/Mayotte' => { + 'StandardTzOffset' => '+0300' + }, + 'America/Argentina/Salta' => { + 'StandardTzOffset' => '-0300' + }, + 'Pacific/Funafuti' => { + 'StandardTzOffset' => '+1200' + }, + 'Europe/Berlin' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Etc/GMT-9' => { + 'StandardTzOffset' => '-0900' + }, + 'Asia/Choibalsan' => { + 'StandardTzOffset' => '+0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=-1SA', + 'DaylightTzOffset' => '+0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SA' + }, + 'America/Montevideo' => { + 'StandardTzOffset' => '-0300', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU', + 'DaylightTzOffset' => '-0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=1SU' + }, + 'America/Belize' => { + 'StandardTzOffset' => '-0600' + }, + 'Africa/Djibouti' => { + 'StandardTzOffset' => '+0300' + }, + 'America/Argentina/San_Juan' => { + 'StandardTzOffset' => '-0300' + }, + 'America/Thunder_Bay' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Hovd' => { + 'StandardTzOffset' => '+0700', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=-1SA', + 'DaylightTzOffset' => '+0800', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SA' + }, + 'Asia/Novokuznetsk' => { + 'StandardTzOffset' => '+0700' + }, + 'Indian/Maldives' => { + 'StandardTzOffset' => '+0500' + }, + 'America/Toronto' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Australia/Eucla' => { + 'StandardTzOffset' => '+0845', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU', + 'DaylightTzOffset' => '+0945', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' + }, + 'Pacific/Galapagos' => { + 'StandardTzOffset' => '-0600' + }, + 'Asia/Tehran' => { + 'StandardTzOffset' => '+0330', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYMONTHDAY=21', + 'DaylightTzOffset' => '+0430', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYMONTHDAY=21' + }, + 'Africa/Malabo' => { + 'StandardTzOffset' => '+0100' + }, + 'America/Martinique' => { + 'StandardTzOffset' => '-0400' + }, + 'Asia/Aden' => { + 'StandardTzOffset' => '+0300' + }, + 'America/Chihuahua' => { + 'StandardTzOffset' => '-0700', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '-0600', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU' + }, + 'Australia/Sydney' => { + 'StandardTzOffset' => '+1000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU', + 'DaylightTzOffset' => '+1100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=1SU' + }, + 'America/Moncton' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Goose_Bay' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Detroit' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Australia/Lindeman' => { + 'StandardTzOffset' => '+1000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=1SU', + 'DaylightTzOffset' => '+1100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' + }, + 'Africa/Mbabane' => { + 'StandardTzOffset' => '+0200' + }, + 'Etc/GMT+4' => { + 'StandardTzOffset' => '+0400' + }, + 'Africa/Lubumbashi' => { + 'StandardTzOffset' => '+0200' + }, + 'America/Asuncion' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=8SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=1SU' + }, + 'Antarctica/Vostok' => { + 'StandardTzOffset' => '+0600' + }, + 'America/Indiana/Petersburg' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Africa/Lome' => { + 'StandardTzOffset' => '+0000' + }, + 'Asia/Harbin' => { + 'StandardTzOffset' => '+0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=3SU', + 'DaylightTzOffset' => '+0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=3SU' + }, + 'America/Montreal' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Tashkent' => { + 'StandardTzOffset' => '+0500' + }, + 'Atlantic/St_Helena' => { + 'StandardTzOffset' => '+0000' + }, + 'Africa/Brazzaville' => { + 'StandardTzOffset' => '+0100' + }, + 'Pacific/Saipan' => { + 'StandardTzOffset' => '+1000' + }, + 'Asia/Ust-Nera' => { + 'StandardTzOffset' => '+1100' + }, + 'Antarctica/Macquarie' => { + 'StandardTzOffset' => '+1100' + }, + 'America/Edmonton' => { + 'StandardTzOffset' => '-0700', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0600', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Yerevan' => { + 'StandardTzOffset' => '+0400' + }, + 'Africa/Dakar' => { + 'StandardTzOffset' => '+0000' + }, + 'Europe/London' => { + 'StandardTzOffset' => '+0000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Indiana/Indianapolis' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Aqtobe' => { + 'StandardTzOffset' => '+0500' + }, + 'Africa/Bamako' => { + 'StandardTzOffset' => '+0000' + }, + 'Australia/Lord_Howe' => { + 'StandardTzOffset' => '+1030', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU', + 'DaylightTzOffset' => '+1100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=1SU' + }, + 'Europe/Budapest' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Europe/Rome' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Etc/GMT+8' => { + 'StandardTzOffset' => '+0800' + }, + 'Pacific/Fakaofo' => { + 'StandardTzOffset' => '+1300' + }, + 'Africa/Maseru' => { + 'StandardTzOffset' => '+0200' + }, + 'Europe/Oslo' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Africa/Asmara' => { + 'StandardTzOffset' => '+0300' + }, + 'Africa/Douala' => { + 'StandardTzOffset' => '+0100' + }, + 'America/Merida' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU' + }, + 'Asia/Brunei' => { + 'StandardTzOffset' => '+0800' + }, + 'Asia/Rangoon' => { + 'StandardTzOffset' => '+0630' + }, + 'America/Thule' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Macau' => { + 'StandardTzOffset' => '+0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=3SU', + 'DaylightTzOffset' => '+0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=3SU' + }, + 'Asia/Oral' => { + 'StandardTzOffset' => '+0500' + }, + 'America/Cancun' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU' + }, + 'Asia/Singapore' => { + 'StandardTzOffset' => '+0800' + }, + 'Asia/Chongqing' => { + 'StandardTzOffset' => '+0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=3SU', + 'DaylightTzOffset' => '+0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=3SU' + }, + 'Etc/GMT-4' => { + 'StandardTzOffset' => '-0400' + }, + 'America/Maceio' => { + 'StandardTzOffset' => '-0300' + }, + 'America/North_Dakota/Center' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Pacific/Easter' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=4SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=1SU' + }, + 'Africa/Johannesburg' => { + 'StandardTzOffset' => '+0200' + }, + 'Europe/Prague' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Resolute' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Indiana/Winamac' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Pacific/Noumea' => { + 'StandardTzOffset' => '+1100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=27', + 'DaylightTzOffset' => '+1200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=12;BYDAY=1SU' + }, + 'Asia/Bishkek' => { + 'StandardTzOffset' => '+0600' + }, + 'Pacific/Chatham' => { + 'StandardTzOffset' => '+1245', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU', + 'DaylightTzOffset' => '+1345', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU' + }, + 'America/Eirunepe' => { + 'StandardTzOffset' => '-0500' + }, + 'America/Rankin_Inlet' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Cambridge_Bay' => { + 'StandardTzOffset' => '-0700', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0600', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Atlantic/South_Georgia' => { + 'StandardTzOffset' => '-0200' + }, + 'Pacific/Tarawa' => { + 'StandardTzOffset' => '+1200' + }, + 'Etc/GMT+12' => { + 'StandardTzOffset' => '+1200' + }, + 'Asia/Yakutsk' => { + 'StandardTzOffset' => '+1000' + }, + 'Pacific/Efate' => { + 'StandardTzOffset' => '+1100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=1;BYDAY=4SU', + 'DaylightTzOffset' => '+1200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=4SU' + }, + 'Pacific/Pitcairn' => { + 'StandardTzOffset' => '-0800' + }, + 'America/Araguaina' => { + 'StandardTzOffset' => '-0300' + }, + 'Atlantic/Cape_Verde' => { + 'StandardTzOffset' => '-0100' + }, + 'Africa/Gaborone' => { + 'StandardTzOffset' => '+0200' + }, + 'Etc/GMT-5' => { + 'StandardTzOffset' => '-0500' + }, + 'America/Argentina/Jujuy' => { + 'StandardTzOffset' => '-0300' + }, + 'Africa/Cairo' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=-1TH', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=-1FR' + }, + 'America/Winnipeg' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Africa/Windhoek' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=1SU' + }, + 'Etc/GMT-8' => { + 'StandardTzOffset' => '-0800' + }, + 'Africa/Casablanca' => { + 'StandardTzOffset' => '+0000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Africa/Kigali' => { + 'StandardTzOffset' => '+0200' + }, + 'Asia/Vientiane' => { + 'StandardTzOffset' => '+0700' + }, + 'Africa/Bangui' => { + 'StandardTzOffset' => '+0100' + }, + 'Asia/Ashgabat' => { + 'StandardTzOffset' => '+0500' + }, + 'Africa/Nouakchott' => { + 'StandardTzOffset' => '+0000' + }, + 'America/Argentina/Tucuman' => { + 'StandardTzOffset' => '-0300', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=3SU', + 'DaylightTzOffset' => '-0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=3SU' + }, + 'Europe/Gibraltar' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Etc/GMT+9' => { + 'StandardTzOffset' => '+0900' + }, + 'America/Pangnirtung' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Sao_Paulo' => { + 'StandardTzOffset' => '-0300', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=2;BYDAY=3SU', + 'DaylightTzOffset' => '-0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=3SU' + }, + 'Asia/Nicosia' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Pacific/Midway' => { + 'StandardTzOffset' => '-1100' + }, + 'Europe/Andorra' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Asia/Riyadh' => { + 'StandardTzOffset' => '+0300' + }, + 'Europe/Athens' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Europe/Volgograd' => { + 'StandardTzOffset' => '+0400' + }, + 'Asia/Qyzylorda' => { + 'StandardTzOffset' => '+0600' + }, + 'Asia/Khandyga' => { + 'StandardTzOffset' => '+1000' + }, + 'Asia/Gaza' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=4FR', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1TH' + }, + 'Asia/Omsk' => { + 'StandardTzOffset' => '+0700' + }, + 'Asia/Tokyo' => { + 'StandardTzOffset' => '+0900' + }, + 'America/Sitka' => { + 'StandardTzOffset' => '-0900', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0800', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Jayapura' => { + 'StandardTzOffset' => '+0900' + }, + 'Asia/Thimphu' => { + 'StandardTzOffset' => '+0600' + }, + 'Antarctica/Syowa' => { + 'StandardTzOffset' => '+0300' + }, + 'America/Port-au-Prince' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Damascus' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1FR', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1FR' + }, + 'America/Indiana/Marengo' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Qatar' => { + 'StandardTzOffset' => '+0300' + }, + 'Europe/Sofia' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Fortaleza' => { + 'StandardTzOffset' => '-0300' + }, + 'America/Mexico_City' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU' + }, + 'Atlantic/Azores' => { + 'StandardTzOffset' => '-0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0000', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Belem' => { + 'StandardTzOffset' => '-0300' + }, + 'Asia/Hong_Kong' => { + 'StandardTzOffset' => '+0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=4SU', + 'DaylightTzOffset' => '+0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=3SU' + }, + 'America/Nome' => { + 'StandardTzOffset' => '-0900', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0800', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Godthab' => { + 'StandardTzOffset' => '-0300', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '-0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Antarctica/Davis' => { + 'StandardTzOffset' => '+0700' + }, + 'America/Scoresbysund' => { + 'StandardTzOffset' => '-0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0000', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Australia/Brisbane' => { + 'StandardTzOffset' => '+1000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=1SU', + 'DaylightTzOffset' => '+1100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' + }, + 'Asia/Baku' => { + 'StandardTzOffset' => '+0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Asia/Kuala_Lumpur' => { + 'StandardTzOffset' => '+0800' + }, + 'Africa/Lagos' => { + 'StandardTzOffset' => '+0100' + }, + 'Indian/Chagos' => { + 'StandardTzOffset' => '+0600' + }, + 'America/Vancouver' => { + 'StandardTzOffset' => '-0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0700', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Asia/Yekaterinburg' => { + 'StandardTzOffset' => '+0600' + }, + 'Pacific/Port_Moresby' => { + 'StandardTzOffset' => '+1000' + }, + 'America/Phoenix' => { + 'StandardTzOffset' => '-0700' + }, + 'Etc/GMT-7' => { + 'StandardTzOffset' => '-0700' + }, + 'Europe/Copenhagen' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Asia/Almaty' => { + 'StandardTzOffset' => '+0600' + }, + 'Etc/UTC' => { + 'StandardTzOffset' => '+0000' + }, + 'Asia/Kathmandu' => { + 'StandardTzOffset' => '+0545' + }, + 'Asia/Dili' => { + 'StandardTzOffset' => '+0900' + }, + 'America/Adak' => { + 'StandardTzOffset' => -1000, + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Argentina/Catamarca' => { + 'StandardTzOffset' => '-0300' + }, + 'America/Caracas' => { + 'StandardTzOffset' => '-0430' + }, + 'Etc/GMT-10' => { + 'StandardTzOffset' => '-1000' + }, + 'America/Curacao' => { + 'StandardTzOffset' => '-0400' + }, + 'America/Tegucigalpa' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=5;BYDAY=1SU' + }, + 'Pacific/Honolulu' => { + 'StandardTzOffset' => '-1000' + }, + 'Pacific/Wallis' => { + 'StandardTzOffset' => '+1200' + }, + 'Africa/Niamey' => { + 'StandardTzOffset' => '+0100' + }, + 'America/Ojinaga' => { + 'StandardTzOffset' => '-0700', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0600', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Europe/Tirane' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Rio_Branco' => { + 'StandardTzOffset' => '-0500' + }, + 'America/Guatemala' => { + 'StandardTzOffset' => '-0600' + }, + 'Africa/Ceuta' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Argentina/San_Luis' => { + 'StandardTzOffset' => '-0300' + }, + 'Africa/Maputo' => { + 'StandardTzOffset' => '+0200' + }, + 'America/Santa_Isabel' => { + 'StandardTzOffset' => '-0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '-0700', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU' + }, + 'America/Managua' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=6;BYDAY=4MO', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=3SU' + }, + 'America/Noronha' => { + 'StandardTzOffset' => '-0200' + }, + 'America/Santiago' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=4SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=1SU' + }, + 'Europe/Lisbon' => { + 'StandardTzOffset' => '+0000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Asia/Kamchatka' => { + 'StandardTzOffset' => '+1200' + }, + 'America/Campo_Grande' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=2;BYDAY=3SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=3SU' + }, + 'America/Lima' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYMONTHDAY=1', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=1;BYMONTHDAY=1' + }, + 'Asia/Bangkok' => { + 'StandardTzOffset' => '+0700' + }, + 'Australia/Darwin' => { + 'StandardTzOffset' => '+0930' + }, + 'America/Metlakatla' => { + 'StandardTzOffset' => '-0800' + }, + 'Asia/Seoul' => { + 'StandardTzOffset' => '+0900', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=2SU', + 'DaylightTzOffset' => '+1000', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=5;BYDAY=2SU' + }, + 'Europe/Luxembourg' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Atlantic/Faroe' => { + 'StandardTzOffset' => '+0000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Boa_Vista' => { + 'StandardTzOffset' => '-0400' + }, + 'Pacific/Apia' => { + 'StandardTzOffset' => '+1300', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU', + 'DaylightTzOffset' => '+1400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU' + }, + 'Antarctica/Mawson' => { + 'StandardTzOffset' => '+0500' + }, + 'Europe/Monaco' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Etc/GMT+13' => { + 'StandardTzOffset' => '+1300' + }, + 'America/Argentina/Buenos_Aires' => { + 'StandardTzOffset' => '-0300', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=3SU', + 'DaylightTzOffset' => '-0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=3SU' + }, + 'Europe/Kiev' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Santo_Domingo' => { + 'StandardTzOffset' => '-0400' + }, + 'Asia/Jakarta' => { + 'StandardTzOffset' => '+0700' + }, + 'Africa/Ndjamena' => { + 'StandardTzOffset' => '+0100' + }, + 'America/Guayaquil' => { + 'StandardTzOffset' => '-0500' + }, + 'America/Chicago' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Europe/Samara' => { + 'StandardTzOffset' => '+0400' + }, + 'America/Indiana/Tell_City' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Europe/Zaporozhye' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Denver' => { + 'StandardTzOffset' => '-0700', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0600', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Pacific/Auckland' => { + 'StandardTzOffset' => '+1200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU', + 'DaylightTzOffset' => '+1300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU' + }, + 'Europe/Vienna' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Grand_Turk' => { + 'StandardTzOffset' => '-0500', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0400', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Argentina/Ushuaia' => { + 'StandardTzOffset' => '-0300' + }, + 'Asia/Kuching' => { + 'StandardTzOffset' => '+0800' + }, + 'Asia/Karachi' => { + 'StandardTzOffset' => '+0500' + }, + 'Africa/Accra' => { + 'StandardTzOffset' => '+0000' + }, + 'America/Port_of_Spain' => { + 'StandardTzOffset' => '-0400' + }, + 'America/Anchorage' => { + 'StandardTzOffset' => '-0900', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0800', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/North_Dakota/Beulah' => { + 'StandardTzOffset' => '-0600', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0500', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'America/Paramaribo' => { + 'StandardTzOffset' => '-0300' + }, + 'Asia/Taipei' => { + 'StandardTzOffset' => '+0800', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYMONTHDAY=1', + 'DaylightTzOffset' => '+0900', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=4;BYMONTHDAY=1' + }, + 'Antarctica/Rothera' => { + 'StandardTzOffset' => '-0300' + }, + 'Europe/Dublin' => { + 'StandardTzOffset' => '+0000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Africa/Freetown' => { + 'StandardTzOffset' => '+0000' + }, + 'Atlantic/Bermuda' => { + 'StandardTzOffset' => '-0400', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU', + 'DaylightTzOffset' => '-0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU' + }, + 'Pacific/Kosrae' => { + 'StandardTzOffset' => '+1100' + }, + 'Europe/Tallinn' => { + 'StandardTzOffset' => '+0200', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0300', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Pacific/Gambier' => { + 'StandardTzOffset' => '-0900' + }, + 'Australia/Hobart' => { + 'StandardTzOffset' => '+1000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=4;BYDAY=1SU', + 'DaylightTzOffset' => '+1100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=1SU' + }, + 'America/Panama' => { + 'StandardTzOffset' => '-0500' + }, + 'Indian/Reunion' => { + 'StandardTzOffset' => '+0400' + }, + 'Europe/Zurich' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Atlantic/Madeira' => { + 'StandardTzOffset' => '+0000', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0100', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'America/Puerto_Rico' => { + 'StandardTzOffset' => '-0400' + }, + 'Europe/Stockholm' => { + 'StandardTzOffset' => '+0100', + 'StandardRRule' => 'FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU', + 'DaylightTzOffset' => '+0200', + 'DaylightRRule' => 'FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' + }, + 'Indian/Mahe' => { + 'StandardTzOffset' => '+0400' + } +} +; +our $ZonesByOffset = { + '-0600' => { + 'N' => [ + [ + '0', + [ + 'America/Managua', + 'America/Monterrey', + 'America/Chihuahua', + 'America/Merida', + 'America/Cancun', + 'America/Matamoros', + 'America/Ojinaga', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '73472400', + [ + 'America/Managua', + 'America/Monterrey', + 'America/Chihuahua', + 'America/Merida', + 'America/Cancun', + 'America/Matamoros', + 'America/Ojinaga', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '105084000', + [ + 'America/Monterrey', + 'America/Chihuahua', + 'America/Merida', + 'America/Cancun', + 'America/Matamoros', + 'America/Ojinaga', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '126687600', + [ + 'America/Monterrey', + 'America/Chihuahua', + 'America/Merida', + 'America/Kentucky/Louisville', + 'America/Cancun', + 'America/Matamoros', + 'America/Ojinaga', + 'America/Swift_Current', + 'America/Indiana/Marengo', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '152092800', + [ + 'America/Monterrey', + 'America/Chihuahua', + 'America/Merida', + 'America/Cancun', + 'America/Matamoros', + 'America/Ojinaga', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '377935200', + [ + 'America/Monterrey', + 'America/Chihuahua', + 'America/Matamoros', + 'America/Ojinaga', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '504939600', + [ + 'America/Monterrey', + 'America/Chihuahua', + 'America/Matamoros', + 'Pacific/Galapagos', + 'America/Ojinaga', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '568015200', + [ + 'America/Chihuahua', + 'Pacific/Galapagos', + 'America/Ojinaga', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '717310800', + [ + 'America/Managua', + 'America/Chihuahua', + 'Pacific/Galapagos', + 'America/Ojinaga', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '725868000', + [ + 'America/Chihuahua', + 'Pacific/Galapagos', + 'America/Ojinaga', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '820476000', + [ + 'Pacific/Galapagos', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '883634400', + [ + 'America/Chihuahua', + 'Pacific/Galapagos', + 'America/Ojinaga', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '891766800', + [ + 'Pacific/Galapagos', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '973400400', + [ + 'Pacific/Galapagos', + 'America/Swift_Current', + 'America/Cambridge_Bay', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '986115600', + [ + 'Pacific/Galapagos', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '1001836800', + [ + 'Pacific/Galapagos', + 'America/Swift_Current', + 'America/Mexico_City', + 'America/Regina', + 'Etc/GMT-6' + ] + ], + [ + '1014184800', + [ + 'Pacific/Galapagos', + 'America/Swift_Current', + 'America/Regina', + 'Etc/GMT-6' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Tegucigalpa', + 'America/Winnipeg', + 'America/Belize', + 'America/Mexico_City', + 'America/Kentucky/Monticello', + 'America/Indiana/Knox', + 'America/Indiana/Petersburg', + 'America/Rankin_Inlet', + 'America/Resolute', + 'America/Rainy_River' + ] + ], + [ + '104914800', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Tegucigalpa', + 'America/Winnipeg', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Indiana/Knox', + 'America/Indiana/Petersburg', + 'America/Rankin_Inlet', + 'America/Resolute', + 'America/Rainy_River' + ] + ], + [ + '161758800', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Tegucigalpa', + 'America/Winnipeg', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Indiana/Knox', + 'America/Indiana/Petersburg', + 'America/Rankin_Inlet', + 'America/Resolute', + 'America/Rainy_River' + ] + ], + [ + '247046400', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Tegucigalpa', + 'America/Winnipeg', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Indiana/Knox', + 'America/Rankin_Inlet', + 'America/Resolute', + 'America/Rainy_River' + ] + ], + [ + '384926400', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Tegucigalpa', + 'America/Winnipeg', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Indiana/Knox', + 'America/Rankin_Inlet', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '407653200', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Indiana/Knox', + 'America/Rankin_Inlet', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '568015200', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Indiana/Knox', + 'America/Rankin_Inlet', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '688550400', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Rankin_Inlet', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '694260000', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Rankin_Inlet', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '720003600', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Rankin_Inlet', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '820476000', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Chihuahua', + 'America/Merida', + 'America/Winnipeg', + 'America/Matamoros', + 'America/Belize', + 'America/Ojinaga', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Rankin_Inlet', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '852094800', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Chihuahua', + 'America/Merida', + 'America/Winnipeg', + 'America/Matamoros', + 'America/Belize', + 'America/Ojinaga', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Rankin_Inlet', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '883634400', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Rankin_Inlet', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '902041200', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Rankin_Inlet', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '941353200', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Iqaluit', + 'America/Rankin_Inlet', + 'America/Pangnirtung', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '941360400', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Kentucky/Monticello', + 'America/Iqaluit', + 'America/Rankin_Inlet', + 'America/Cambridge_Bay', + 'America/Pangnirtung', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '972806400', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/North_Dakota/Center', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '986112000', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Rankin_Inlet', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '1001836800', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Menominee', + 'America/Rankin_Inlet', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '1014184800', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Rankin_Inlet', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '1067158800', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Rankin_Inlet', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '1143961200', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Indiana/Vincennes', + 'America/Mexico_City', + 'America/Menominee', + 'America/Indiana/Tell_City', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Rankin_Inlet', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '1162108800', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Indiana/Vincennes', + 'America/Mexico_City', + 'America/Menominee', + 'America/Indiana/Tell_City', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Rankin_Inlet', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '1173600000', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Indiana/Vincennes', + 'America/Mexico_City', + 'America/Menominee', + 'America/Indiana/Tell_City', + 'America/Indiana/Knox', + 'America/Indiana/Petersburg', + 'America/Rankin_Inlet', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '1194163200', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Mexico_City', + 'America/Menominee', + 'America/Indiana/Tell_City', + 'America/Indiana/Knox', + 'America/Rankin_Inlet', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '1270371600', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Bahia_Banderas', + 'America/Mexico_City', + 'America/Menominee', + 'America/Indiana/Tell_City', + 'America/Indiana/Knox', + 'America/Rankin_Inlet', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ], + [ + '1289120400', + [ + 'America/Guatemala', + 'America/El_Salvador', + 'America/Costa_Rica', + 'America/Chicago', + 'America/Managua', + 'America/Monterrey', + 'America/Tegucigalpa', + 'America/Merida', + 'America/Winnipeg', + 'America/Cancun', + 'America/Matamoros', + 'America/Belize', + 'America/Bahia_Banderas', + 'America/Mexico_City', + 'America/Menominee', + 'America/Indiana/Tell_City', + 'America/Indiana/Knox', + 'America/North_Dakota/Beulah', + 'America/Rankin_Inlet', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'America/Resolute', + 'America/Rainy_River', + 'Pacific/Easter' + ] + ] + ] + }, + '+0730' => { + 'N' => [ + [ + '0', + [ + 'Asia/Singapore', + 'Asia/Kuala_Lumpur' + ] + ] + ] + }, + '-0830' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Pitcairn' + ] + ] + ] + }, + '+1200' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Tarawa', + 'Pacific/Wake', + 'Pacific/Majuro', + 'Pacific/Wallis', + 'Pacific/Kosrae', + 'Pacific/Funafuti', + 'Etc/GMT+12' + ] + ], + [ + '294323400', + [ + 'Pacific/Tarawa', + 'Pacific/Wake', + 'Pacific/Majuro', + 'Pacific/Wallis', + 'Pacific/Nauru', + 'Pacific/Kosrae', + 'Pacific/Funafuti', + 'Etc/GMT+12' + ] + ], + [ + '745848000', + [ + 'Pacific/Tarawa', + 'Pacific/Wake', + 'Pacific/Majuro', + 'Pacific/Kwajalein', + 'Pacific/Wallis', + 'Pacific/Nauru', + 'Pacific/Kosrae', + 'Pacific/Funafuti', + 'Etc/GMT+12' + ] + ], + [ + '915105600', + [ + 'Pacific/Tarawa', + 'Pacific/Wake', + 'Pacific/Majuro', + 'Pacific/Kwajalein', + 'Pacific/Wallis', + 'Pacific/Nauru', + 'Pacific/Funafuti', + 'Etc/GMT+12' + ] + ], + [ + '1301151600', + [ + 'Asia/Kamchatka', + 'Asia/Magadan', + 'Asia/Ust-Nera', + 'Pacific/Tarawa', + 'Pacific/Wake', + 'Pacific/Majuro', + 'Pacific/Kwajalein', + 'Asia/Anadyr', + 'Pacific/Wallis', + 'Pacific/Nauru', + 'Pacific/Funafuti', + 'Etc/GMT+12' + ] + ], + [ + '1315828800', + [ + 'Asia/Kamchatka', + 'Asia/Magadan', + 'Pacific/Tarawa', + 'Pacific/Wake', + 'Pacific/Majuro', + 'Pacific/Kwajalein', + 'Asia/Anadyr', + 'Pacific/Wallis', + 'Pacific/Nauru', + 'Pacific/Funafuti', + 'Etc/GMT+12' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Pacific/Fiji', + 'Pacific/Auckland', + 'Asia/Kamchatka' + ] + ], + [ + '386420400', + [ + 'Pacific/Fiji', + 'Pacific/Auckland', + 'Asia/Kamchatka', + 'Asia/Anadyr' + ] + ], + [ + '670341600', + [ + 'Pacific/Fiji', + 'Pacific/Auckland' + ] + ], + [ + '695746800', + [ + 'Pacific/Fiji', + 'Pacific/Auckland', + 'Asia/Kamchatka', + 'Asia/Anadyr' + ] + ], + [ + '1269698400', + [ + 'Pacific/Fiji', + 'Pacific/Auckland' + ] + ] + ] + }, + '-0700' => { + 'N' => [ + [ + '0', + [ + 'America/Phoenix', + 'America/Swift_Current', + 'America/Creston', + 'Etc/GMT-7' + ] + ], + [ + '73472400', + [ + 'America/Phoenix', + 'America/Creston', + 'Etc/GMT-7' + ] + ], + [ + '84016800', + [ + 'America/Phoenix', + 'America/Dawson_Creek', + 'America/Creston', + 'Etc/GMT-7' + ] + ], + [ + '126255600', + [ + 'America/Phoenix', + 'America/Boise', + 'America/Dawson_Creek', + 'America/Creston', + 'Etc/GMT-7' + ] + ], + [ + '129114000', + [ + 'America/Phoenix', + 'America/Dawson_Creek', + 'America/Creston', + 'Etc/GMT-7' + ] + ], + [ + '915174000', + [ + 'America/Phoenix', + 'America/Hermosillo', + 'America/Dawson_Creek', + 'America/Creston', + 'Etc/GMT-7' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'America/Denver', + 'America/Boise', + 'America/Yellowknife', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'Pacific/Easter' + ] + ], + [ + '28800', + [ + 'America/Hermosillo', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Bahia_Banderas', + 'America/Yellowknife', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'Pacific/Easter' + ] + ], + [ + '126255600', + [ + 'America/Hermosillo', + 'America/Denver', + 'America/Mazatlan', + 'America/Bahia_Banderas', + 'America/Yellowknife', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'Pacific/Easter' + ] + ], + [ + '129114000', + [ + 'America/Hermosillo', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Bahia_Banderas', + 'America/Yellowknife', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'Pacific/Easter' + ] + ], + [ + '294228000', + [ + 'America/Hermosillo', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Bahia_Banderas', + 'America/Yellowknife', + 'America/Inuvik', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center', + 'Pacific/Easter' + ] + ], + [ + '384926400', + [ + 'America/Hermosillo', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Bahia_Banderas', + 'America/Yellowknife', + 'America/Inuvik', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton', + 'America/North_Dakota/New_Salem', + 'America/North_Dakota/Center' + ] + ], + [ + '720003600', + [ + 'America/Hermosillo', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Bahia_Banderas', + 'America/Yellowknife', + 'America/Inuvik', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton', + 'America/North_Dakota/New_Salem' + ] + ], + [ + '891766800', + [ + 'America/Chihuahua', + 'America/Hermosillo', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Bahia_Banderas', + 'America/Ojinaga', + 'America/Yellowknife', + 'America/Inuvik', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton', + 'America/North_Dakota/New_Salem' + ] + ], + [ + '915174000', + [ + 'America/Chihuahua', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Bahia_Banderas', + 'America/Ojinaga', + 'America/Yellowknife', + 'America/Inuvik', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton', + 'America/North_Dakota/New_Salem' + ] + ], + [ + '941360400', + [ + 'America/Chihuahua', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Bahia_Banderas', + 'America/Ojinaga', + 'America/Yellowknife', + 'America/Inuvik', + 'America/North_Dakota/Beulah', + 'America/Edmonton', + 'America/North_Dakota/New_Salem' + ] + ], + [ + '986115600', + [ + 'America/Chihuahua', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Bahia_Banderas', + 'America/Ojinaga', + 'America/Yellowknife', + 'America/Inuvik', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton', + 'America/North_Dakota/New_Salem' + ] + ], + [ + '1067158800', + [ + 'America/Chihuahua', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Bahia_Banderas', + 'America/Ojinaga', + 'America/Yellowknife', + 'America/Inuvik', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton' + ] + ], + [ + '1270371600', + [ + 'America/Chihuahua', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Ojinaga', + 'America/Yellowknife', + 'America/Inuvik', + 'America/North_Dakota/Beulah', + 'America/Cambridge_Bay', + 'America/Edmonton' + ] + ], + [ + '1289120400', + [ + 'America/Chihuahua', + 'America/Denver', + 'America/Mazatlan', + 'America/Boise', + 'America/Ojinaga', + 'America/Yellowknife', + 'America/Inuvik', + 'America/Cambridge_Bay', + 'America/Edmonton' + ] + ] + ] + }, + '-0044' => { + 'N' => [ + [ + '0', + [ + 'Africa/Monrovia' + ] + ] + ] + }, + '+1245' => { + 'Y' => [ + [ + '0', + [ + 'Pacific/Chatham' + ] + ] + ] + }, + '+0930' => { + 'N' => [ + [ + '0', + [ + 'Australia/Adelaide', + 'Australia/Darwin', + 'Australia/Broken_Hill' + ] + ], + [ + '31501800', + [ + 'Australia/Darwin' + ] + ] + ], + 'Y' => [ + [ + '31501800', + [ + 'Australia/Adelaide', + 'Australia/Broken_Hill' + ] + ] + ] + }, + '-0330' => { + 'N' => [ + [ + '0', + [ + 'America/Paramaribo' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'America/St_Johns' + ] + ] + ] + }, + '-0100' => { + 'N' => [ + [ + '0', + [ + 'Africa/El_Aaiun', + 'Africa/Bissau', + 'Etc/GMT-1' + ] + ], + [ + '157770000', + [ + 'Africa/El_Aaiun', + 'Etc/GMT-1' + ] + ], + [ + '186120000', + [ + 'Atlantic/Cape_Verde', + 'Africa/El_Aaiun', + 'Etc/GMT-1' + ] + ], + [ + '198291600', + [ + 'Atlantic/Cape_Verde', + 'Etc/GMT-1' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Atlantic/Azores' + ] + ], + [ + '354679200', + [ + 'Atlantic/Azores', + 'America/Scoresbysund' + ] + ], + [ + '717559200', + [ + 'America/Scoresbysund' + ] + ], + [ + '733280400', + [ + 'Atlantic/Azores', + 'America/Scoresbysund' + ] + ] + ] + }, + '-1200' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Kwajalein', + 'Etc/GMT-12', + 'Pacific/Enderbury' + ] + ], + [ + '307627200', + [ + 'Pacific/Kwajalein', + 'Etc/GMT-12' + ] + ], + [ + '745848000', + [ + 'Etc/GMT-12' + ] + ] + ] + }, + '+0300' => { + 'N' => [ + [ + '0', + [ + 'Asia/Baghdad', + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '76190400', + [ + 'Asia/Baghdad', + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '389048400', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '631141200', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Europe/Kiev', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Europe/Minsk', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Europe/Chisinau', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Europe/Uzhgorod', + 'Antarctica/Syowa', + 'Etc/GMT+3', + 'Europe/Simferopol' + ] + ], + [ + '641941200', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Europe/Kiev', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Europe/Minsk', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Europe/Uzhgorod', + 'Antarctica/Syowa', + 'Etc/GMT+3', + 'Europe/Simferopol' + ] + ], + [ + '646786800', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Europe/Minsk', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '670370400', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Baku', + 'Asia/Qatar', + 'Europe/Minsk', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '670374000', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Baku', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '671144400', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Baku', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Asia/Yerevan', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '683499600', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Asia/Yerevan', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '685573200', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '686102400', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Europe/Samara', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '687916800', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '828230400', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3', + 'Europe/Simferopol' + ] + ], + [ + '846374400', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '852066000', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3', + 'Europe/Simferopol' + ] + ], + [ + '859683600', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Africa/Kampala', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '947930400', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Africa/Kampala', + 'Africa/Khartoum', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '1301184000', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Europe/Minsk', + 'Africa/Kampala', + 'Africa/Khartoum', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Europe/Kaliningrad', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ], + [ + '1351202400', + [ + 'Asia/Riyadh', + 'Africa/Nairobi', + 'Asia/Kuwait', + 'Africa/Addis_Ababa', + 'Africa/Dar_es_Salaam', + 'Africa/Mogadishu', + 'Asia/Qatar', + 'Europe/Minsk', + 'Africa/Kampala', + 'Africa/Khartoum', + 'Indian/Antananarivo', + 'Asia/Bahrain', + 'Asia/Amman', + 'Africa/Djibouti', + 'Asia/Aden', + 'Africa/Asmara', + 'Europe/Kaliningrad', + 'Indian/Comoro', + 'Indian/Mayotte', + 'Antarctica/Syowa', + 'Etc/GMT+3' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Europe/Moscow', + 'Europe/Kiev', + 'Europe/Minsk', + 'Europe/Zaporozhye', + 'Europe/Riga', + 'Europe/Chisinau', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Europe/Uzhgorod', + 'Europe/Simferopol' + ] + ], + [ + '277250400', + [ + 'Europe/Istanbul', + 'Europe/Moscow', + 'Europe/Kiev', + 'Europe/Minsk', + 'Europe/Zaporozhye', + 'Europe/Riga', + 'Europe/Chisinau', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Europe/Uzhgorod', + 'Europe/Simferopol' + ] + ], + [ + '389048400', + [ + 'Europe/Istanbul', + 'Europe/Moscow', + 'Asia/Baghdad', + 'Europe/Kiev', + 'Europe/Minsk', + 'Europe/Zaporozhye', + 'Europe/Riga', + 'Europe/Chisinau', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Europe/Uzhgorod', + 'Europe/Simferopol' + ] + ], + [ + '482792400', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Europe/Kiev', + 'Europe/Minsk', + 'Europe/Zaporozhye', + 'Europe/Riga', + 'Europe/Chisinau', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Europe/Uzhgorod', + 'Europe/Simferopol' + ] + ], + [ + '606866400', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Europe/Kiev', + 'Europe/Minsk', + 'Europe/Samara', + 'Europe/Volgograd', + 'Europe/Zaporozhye', + 'Europe/Riga', + 'Europe/Chisinau', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Europe/Uzhgorod', + 'Europe/Simferopol' + ] + ], + [ + '606870000', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Europe/Kiev', + 'Europe/Minsk', + 'Europe/Samara', + 'Europe/Volgograd', + 'Europe/Zaporozhye', + 'Europe/Chisinau', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Uzhgorod', + 'Europe/Simferopol' + ] + ], + [ + '631141200', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Europe/Samara', + 'Europe/Volgograd', + 'Europe/Zaporozhye', + 'Europe/Vilnius', + 'Europe/Kaliningrad' + ] + ], + [ + '670374000', + [ + 'Asia/Baghdad' + ] + ], + [ + '671144400', + [ + 'Asia/Baghdad', + 'Asia/Tbilisi' + ] + ], + [ + '683499600', + [ + 'Asia/Baghdad', + 'Asia/Baku', + 'Asia/Tbilisi' + ] + ], + [ + '685573200', + [ + 'Asia/Baghdad', + 'Asia/Baku', + 'Asia/Yerevan', + 'Asia/Tbilisi' + ] + ], + [ + '695779200', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Asia/Baku', + 'Asia/Yerevan', + 'Asia/Tbilisi' + ] + ], + [ + '701820000', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Asia/Baku', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Europe/Volgograd' + ] + ], + [ + '717537600', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Europe/Volgograd' + ] + ], + [ + '767743200', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Europe/Volgograd', + 'Europe/Simferopol' + ] + ], + [ + '780440400', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Asia/Yerevan', + 'Europe/Volgograd', + 'Europe/Simferopol' + ] + ], + [ + '811897200', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Europe/Volgograd', + 'Europe/Simferopol' + ] + ], + [ + '828230400', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Europe/Volgograd' + ] + ], + [ + '846374400', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Europe/Volgograd', + 'Europe/Simferopol' + ] + ], + [ + '852066000', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Europe/Volgograd' + ] + ], + [ + '1088280000', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Asia/Tbilisi', + 'Europe/Volgograd' + ] + ], + [ + '1111878000', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Europe/Volgograd' + ] + ], + [ + '1269727200', + [ + 'Europe/Moscow', + 'Asia/Baghdad', + 'Europe/Samara', + 'Europe/Volgograd' + ] + ], + [ + '1301180400', + [ + 'Asia/Baghdad' + ] + ] + ] + }, + '-0900' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Gambier', + 'Etc/GMT-9' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'America/Dawson', + 'America/Yakutat' + ] + ], + [ + '120646800', + [ + 'America/Yakutat' + ] + ], + [ + '325677600', + [ + 'America/Juneau', + 'America/Yakutat' + ] + ], + [ + '341406000', + [ + 'America/Yakutat' + ] + ], + [ + '436356000', + [ + 'America/Juneau', + 'America/Sitka', + 'America/Yakutat' + ] + ], + [ + '436363200', + [ + 'America/Anchorage', + 'America/Juneau', + 'America/Sitka', + 'America/Yakutat' + ] + ], + [ + '436366800', + [ + 'America/Anchorage', + 'America/Juneau', + 'America/Sitka', + 'America/Nome', + 'America/Yakutat' + ] + ] + ] + }, + '+0400' => { + 'N' => [ + [ + '0', + [ + 'Asia/Dubai', + 'Asia/Qatar', + 'Asia/Bahrain', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '76190400', + [ + 'Asia/Dubai', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '662673600', + [ + 'Asia/Dubai', + 'Indian/Reunion', + 'Asia/Oral', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '670374000', + [ + 'Asia/Dubai', + 'Europe/Volgograd', + 'Indian/Reunion', + 'Asia/Oral', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '692827200', + [ + 'Asia/Dubai', + 'Europe/Volgograd', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '701820000', + [ + 'Asia/Dubai', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '717537600', + [ + 'Asia/Baku', + 'Asia/Dubai', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '811897200', + [ + 'Asia/Baku', + 'Asia/Dubai', + 'Asia/Yerevan', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '820440000', + [ + 'Asia/Dubai', + 'Asia/Yerevan', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '846360000', + [ + 'Asia/Dubai', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '852062400', + [ + 'Asia/Dubai', + 'Asia/Tbilisi', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '859665600', + [ + 'Asia/Dubai', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '1111878000', + [ + 'Asia/Dubai', + 'Asia/Tbilisi', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '1301180400', + [ + 'Europe/Moscow', + 'Asia/Dubai', + 'Europe/Samara', + 'Asia/Tbilisi', + 'Europe/Volgograd', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ], + [ + '1332626400', + [ + 'Europe/Moscow', + 'Asia/Dubai', + 'Europe/Samara', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Europe/Volgograd', + 'Indian/Reunion', + 'Indian/Mahe', + 'Asia/Muscat', + 'Etc/GMT+4' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Europe/Volgograd' + ] + ], + [ + '247177800', + [ + 'Asia/Tehran', + 'Asia/Baku', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Europe/Volgograd' + ] + ], + [ + '283982400', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Europe/Volgograd' + ] + ], + [ + '606862800', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Europe/Volgograd', + 'Asia/Oral' + ] + ], + [ + '606866400', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Asia/Oral' + ] + ], + [ + '662673600', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Asia/Yerevan', + 'Asia/Tbilisi' + ] + ], + [ + '670366800', + [ + 'Asia/Baku', + 'Asia/Yekaterinburg', + 'Indian/Mauritius', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Asia/Ashgabat' + ] + ], + [ + '670370400', + [ + 'Asia/Yekaterinburg', + 'Indian/Mauritius', + 'Asia/Ashgabat' + ] + ], + [ + '687916800', + [ + 'Asia/Yekaterinburg', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Ashgabat' + ] + ], + [ + '692827200', + [ + 'Asia/Yekaterinburg', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Ashgabat', + 'Asia/Oral' + ] + ], + [ + '695772000', + [ + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Oral' + ] + ], + [ + '780440400', + [ + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Tbilisi', + 'Asia/Oral' + ] + ], + [ + '796165200', + [ + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Tbilisi', + 'Asia/Oral', + 'Asia/Aqtau' + ] + ], + [ + '820440000', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Tbilisi', + 'Asia/Oral', + 'Asia/Aqtau' + ] + ], + [ + '846360000', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Oral', + 'Asia/Aqtau' + ] + ], + [ + '852062400', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Yerevan', + 'Asia/Oral', + 'Asia/Aqtau' + ] + ], + [ + '859665600', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Yerevan', + 'Asia/Tbilisi', + 'Asia/Oral', + 'Asia/Aqtau' + ] + ], + [ + '1088280000', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Yerevan', + 'Asia/Oral', + 'Asia/Aqtau' + ] + ], + [ + '1110830400', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Europe/Samara', + 'Asia/Yerevan' + ] + ], + [ + '1269727200', + [ + 'Asia/Baku', + 'Indian/Mauritius', + 'Asia/Yerevan' + ] + ], + [ + '1332626400', + [ + 'Asia/Baku', + 'Indian/Mauritius' + ] + ] + ] + }, + '-1000' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Honolulu', + 'Pacific/Tahiti', + 'Etc/GMT-10' + ] + ], + [ + '307622400', + [ + 'Pacific/Honolulu', + 'Pacific/Tahiti', + 'Etc/GMT-10', + 'Pacific/Kiritimati' + ] + ], + [ + '788954400', + [ + 'Pacific/Honolulu', + 'Pacific/Tahiti', + 'Etc/GMT-10' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'America/Anchorage' + ] + ], + [ + '279714600', + [ + 'America/Anchorage', + 'Pacific/Rarotonga' + ] + ], + [ + '436363200', + [ + 'Pacific/Rarotonga' + ] + ], + [ + '436366800', + [ + 'Pacific/Rarotonga', + 'America/Adak' + ] + ] + ] + }, + '+0500' => { + 'N' => [ + [ + '0', + [ + 'Asia/Karachi', + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Asia/Oral', + 'Asia/Qyzylorda', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Asia/Kashgar', + 'Etc/GMT+5', + 'Indian/Chagos' + ] + ], + [ + '38775600', + [ + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Asia/Oral', + 'Asia/Qyzylorda', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Asia/Kashgar', + 'Etc/GMT+5', + 'Indian/Chagos' + ] + ], + [ + '325969200', + [ + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Asia/Oral', + 'Asia/Qyzylorda', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Etc/GMT+5', + 'Indian/Chagos' + ] + ], + [ + '370724400', + [ + 'Indian/Maldives', + 'Indian/Kerguelen', + 'Etc/GMT+5', + 'Indian/Chagos' + ] + ], + [ + '662670000', + [ + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Qyzylorda', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Etc/GMT+5', + 'Indian/Chagos' + ] + ], + [ + '670363200', + [ + 'Asia/Bishkek', + 'Asia/Dushanbe', + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Qyzylorda', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Etc/GMT+5', + 'Indian/Chagos' + ] + ], + [ + '683586000', + [ + 'Asia/Dushanbe', + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Qyzylorda', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Etc/GMT+5', + 'Indian/Chagos' + ] + ], + [ + '692823600', + [ + 'Asia/Dushanbe', + 'Indian/Maldives', + 'Asia/Qyzylorda', + 'Indian/Kerguelen', + 'Etc/GMT+5', + 'Indian/Chagos' + ] + ], + [ + '694206000', + [ + 'Asia/Tashkent', + 'Asia/Dushanbe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Asia/Qyzylorda', + 'Indian/Kerguelen', + 'Etc/GMT+5', + 'Indian/Chagos' + ] + ], + [ + '695768400', + [ + 'Asia/Tashkent', + 'Asia/Dushanbe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Indian/Kerguelen', + 'Etc/GMT+5', + 'Indian/Chagos' + ] + ], + [ + '695772000', + [ + 'Asia/Tashkent', + 'Asia/Ashgabat', + 'Asia/Dushanbe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Indian/Kerguelen', + 'Etc/GMT+5', + 'Indian/Chagos' + ] + ], + [ + '820436400', + [ + 'Asia/Tashkent', + 'Asia/Ashgabat', + 'Asia/Dushanbe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Indian/Kerguelen', + 'Etc/GMT+5' + ] + ], + [ + '1110826800', + [ + 'Asia/Tashkent', + 'Asia/Ashgabat', + 'Asia/Dushanbe', + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Indian/Kerguelen', + 'Etc/GMT+5' + ] + ], + [ + '1110830400', + [ + 'Asia/Tashkent', + 'Asia/Ashgabat', + 'Asia/Dushanbe', + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Asia/Oral', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Etc/GMT+5' + ] + ], + [ + '1255806000', + [ + 'Asia/Tashkent', + 'Asia/Ashgabat', + 'Asia/Dushanbe', + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Asia/Oral', + 'Antarctica/Davis', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Etc/GMT+5' + ] + ], + [ + '1255809600', + [ + 'Asia/Tashkent', + 'Asia/Ashgabat', + 'Asia/Dushanbe', + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Asia/Oral', + 'Antarctica/Davis', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Antarctica/Mawson', + 'Etc/GMT+5' + ] + ], + [ + '1268251200', + [ + 'Asia/Tashkent', + 'Asia/Ashgabat', + 'Asia/Dushanbe', + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Asia/Oral', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Antarctica/Mawson', + 'Etc/GMT+5' + ] + ], + [ + '1319742000', + [ + 'Asia/Tashkent', + 'Asia/Ashgabat', + 'Asia/Dushanbe', + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Asia/Oral', + 'Antarctica/Davis', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Antarctica/Mawson', + 'Etc/GMT+5' + ] + ], + [ + '1329854400', + [ + 'Asia/Tashkent', + 'Asia/Ashgabat', + 'Asia/Dushanbe', + 'Asia/Aqtobe', + 'Indian/Maldives', + 'Asia/Samarkand', + 'Asia/Oral', + 'Asia/Aqtau', + 'Indian/Kerguelen', + 'Antarctica/Mawson', + 'Etc/GMT+5' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Asia/Yekaterinburg', + 'Asia/Ashgabat' + ] + ], + [ + '38775600', + [ + 'Asia/Karachi', + 'Asia/Yekaterinburg', + 'Asia/Ashgabat' + ] + ], + [ + '386445600', + [ + 'Asia/Karachi', + 'Asia/Yekaterinburg', + 'Asia/Ashgabat', + 'Asia/Aqtobe', + 'Asia/Samarkand', + 'Asia/Oral', + 'Asia/Qyzylorda', + 'Asia/Aqtau' + ] + ], + [ + '606862800', + [ + 'Asia/Karachi', + 'Asia/Yekaterinburg', + 'Asia/Ashgabat', + 'Asia/Aqtobe', + 'Asia/Samarkand', + 'Asia/Qyzylorda', + 'Asia/Aqtau' + ] + ], + [ + '662670000', + [ + 'Asia/Karachi', + 'Asia/Yekaterinburg', + 'Asia/Ashgabat', + 'Asia/Samarkand' + ] + ], + [ + '670363200', + [ + 'Asia/Karachi', + 'Asia/Tashkent', + 'Asia/Yekaterinburg', + 'Asia/Omsk', + 'Asia/Ashgabat', + 'Asia/Samarkand' + ] + ], + [ + '670366800', + [ + 'Asia/Karachi', + 'Asia/Tashkent', + 'Asia/Omsk', + 'Asia/Samarkand' + ] + ], + [ + '683586000', + [ + 'Asia/Karachi', + 'Asia/Tashkent', + 'Asia/Omsk', + 'Asia/Bishkek', + 'Asia/Samarkand' + ] + ], + [ + '692823600', + [ + 'Asia/Karachi', + 'Asia/Tashkent', + 'Asia/Omsk', + 'Asia/Bishkek', + 'Asia/Aqtobe', + 'Asia/Samarkand', + 'Asia/Aqtau' + ] + ], + [ + '694206000', + [ + 'Asia/Karachi', + 'Asia/Omsk', + 'Asia/Bishkek', + 'Asia/Aqtobe', + 'Asia/Aqtau' + ] + ], + [ + '695768400', + [ + 'Asia/Karachi', + 'Asia/Bishkek', + 'Asia/Aqtobe', + 'Asia/Aqtau' + ] + ], + [ + '695772000', + [ + 'Asia/Karachi', + 'Asia/Yekaterinburg', + 'Asia/Bishkek', + 'Asia/Aqtobe', + 'Asia/Aqtau' + ] + ], + [ + '796165200', + [ + 'Asia/Karachi', + 'Asia/Yekaterinburg', + 'Asia/Bishkek', + 'Asia/Aqtobe' + ] + ], + [ + '1110826800', + [ + 'Asia/Karachi', + 'Asia/Yekaterinburg', + 'Asia/Bishkek' + ] + ], + [ + '1123786800', + [ + 'Asia/Karachi', + 'Asia/Yekaterinburg' + ] + ], + [ + '1301173200', + [ + 'Asia/Karachi' + ] + ] + ] + }, + '+0600' => { + 'N' => [ + [ + '0', + [ + 'Asia/Dhaka', + 'Asia/Urumqi', + 'Asia/Hovd', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6' + ] + ], + [ + '252439200', + [ + 'Asia/Dhaka', + 'Asia/Urumqi', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6' + ] + ], + [ + '325965600', + [ + 'Asia/Dhaka', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6' + ] + ], + [ + '370724400', + [ + 'Asia/Dhaka', + 'Asia/Aqtobe', + 'Asia/Samarkand', + 'Asia/Oral', + 'Asia/Qyzylorda', + 'Asia/Aqtau', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6' + ] + ], + [ + '386445600', + [ + 'Asia/Dhaka', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6' + ] + ], + [ + '560025000', + [ + 'Asia/Dhaka', + 'Asia/Thimphu', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6' + ] + ], + [ + '662666400', + [ + 'Asia/Dhaka', + 'Asia/Almaty', + 'Asia/Thimphu', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6' + ] + ], + [ + '694202400', + [ + 'Asia/Dhaka', + 'Asia/Thimphu', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6' + ] + ], + [ + '820436400', + [ + 'Asia/Dhaka', + 'Asia/Thimphu', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6', + 'Indian/Chagos' + ] + ], + [ + '846266400', + [ + 'Asia/Dhaka', + 'Asia/Colombo', + 'Asia/Thimphu', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6', + 'Indian/Chagos' + ] + ], + [ + '1110823200', + [ + 'Asia/Dhaka', + 'Asia/Almaty', + 'Asia/Colombo', + 'Asia/Qyzylorda', + 'Asia/Thimphu', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6', + 'Indian/Chagos' + ] + ], + [ + '1123786800', + [ + 'Asia/Dhaka', + 'Asia/Almaty', + 'Asia/Bishkek', + 'Asia/Colombo', + 'Asia/Qyzylorda', + 'Asia/Thimphu', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6', + 'Indian/Chagos' + ] + ], + [ + '1145039400', + [ + 'Asia/Dhaka', + 'Asia/Almaty', + 'Asia/Bishkek', + 'Asia/Qyzylorda', + 'Asia/Thimphu', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6', + 'Indian/Chagos' + ] + ], + [ + '1230746400', + [ + 'Asia/Almaty', + 'Asia/Bishkek', + 'Asia/Qyzylorda', + 'Asia/Thimphu', + 'Antarctica/Vostok', + 'Antarctica/Mawson', + 'Etc/GMT+6', + 'Indian/Chagos' + ] + ], + [ + '1255809600', + [ + 'Asia/Almaty', + 'Asia/Bishkek', + 'Asia/Qyzylorda', + 'Asia/Thimphu', + 'Antarctica/Vostok', + 'Etc/GMT+6', + 'Indian/Chagos' + ] + ], + [ + '1301173200', + [ + 'Asia/Almaty', + 'Asia/Yekaterinburg', + 'Asia/Bishkek', + 'Asia/Qyzylorda', + 'Asia/Thimphu', + 'Antarctica/Vostok', + 'Etc/GMT+6', + 'Indian/Chagos' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Asia/Tashkent', + 'Asia/Almaty', + 'Asia/Omsk', + 'Asia/Bishkek', + 'Asia/Dushanbe' + ] + ], + [ + '662666400', + [ + 'Asia/Tashkent', + 'Asia/Omsk', + 'Asia/Bishkek', + 'Asia/Dushanbe' + ] + ], + [ + '670359600', + [ + 'Asia/Tashkent', + 'Asia/Omsk', + 'Asia/Krasnoyarsk', + 'Asia/Bishkek', + 'Asia/Dushanbe', + 'Asia/Novokuznetsk', + 'Asia/Novosibirsk' + ] + ], + [ + '670363200', + [ + 'Asia/Krasnoyarsk', + 'Asia/Novokuznetsk', + 'Asia/Novosibirsk' + ] + ], + [ + '694202400', + [ + 'Asia/Almaty', + 'Asia/Krasnoyarsk', + 'Asia/Novokuznetsk', + 'Asia/Novosibirsk' + ] + ], + [ + '695764800', + [ + 'Asia/Almaty' + ] + ], + [ + '695768400', + [ + 'Asia/Almaty', + 'Asia/Omsk', + 'Asia/Qyzylorda' + ] + ], + [ + '738090000', + [ + 'Asia/Almaty', + 'Asia/Omsk', + 'Asia/Qyzylorda', + 'Asia/Novosibirsk' + ] + ], + [ + '1110823200', + [ + 'Asia/Omsk', + 'Asia/Novosibirsk' + ] + ], + [ + '1230746400', + [ + 'Asia/Dhaka', + 'Asia/Omsk', + 'Asia/Novosibirsk' + ] + ], + [ + '1269716400', + [ + 'Asia/Dhaka', + 'Asia/Omsk', + 'Asia/Novokuznetsk', + 'Asia/Novosibirsk' + ] + ], + [ + '1301169600', + [ + 'Asia/Dhaka' + ] + ] + ] + }, + '-1130' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Niue' + ] + ] + ] + }, + '-0300' => { + 'N' => [ + [ + '0', + [ + 'America/Cayenne', + 'America/Godthab', + 'America/Danmarkshavn', + 'Etc/GMT-3' + ] + ], + [ + '86760000', + [ + 'America/Asuncion', + 'America/Cayenne', + 'America/Godthab', + 'America/Danmarkshavn', + 'Etc/GMT-3' + ] + ], + [ + '134017200', + [ + 'America/Cayenne', + 'America/Godthab', + 'America/Danmarkshavn', + 'Etc/GMT-3' + ] + ], + [ + '176010300', + [ + 'America/Guyana', + 'America/Cayenne', + 'America/Godthab', + 'America/Danmarkshavn', + 'Etc/GMT-3' + ] + ], + [ + '218246400', + [ + 'America/Guyana', + 'America/Cayenne', + 'America/Godthab', + 'America/Danmarkshavn', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '323845200', + [ + 'America/Guyana', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '326001600', + [ + 'America/Guyana', + 'America/Cayenne', + 'America/Miquelon', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '465449400', + [ + 'America/Guyana', + 'America/Paramaribo', + 'America/Cayenne', + 'America/Miquelon', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '536468400', + [ + 'America/Guyana', + 'America/Paramaribo', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '590036400', + [ + 'America/Belem', + 'America/Guyana', + 'America/Paramaribo', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '631162800', + [ + 'America/Belem', + 'America/Guyana', + 'America/Paramaribo', + 'America/Argentina/San_Luis', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '637383600', + [ + 'America/Belem', + 'America/Guyana', + 'America/Paramaribo', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '653540400', + [ + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Guyana', + 'America/Paramaribo', + 'America/Araguaina', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '662698800', + [ + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Paramaribo', + 'America/Araguaina', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '675748800', + [ + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Paramaribo', + 'America/Argentina/San_Luis', + 'America/Araguaina', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '686721600', + [ + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Jujuy', + 'America/Paramaribo', + 'America/Argentina/San_Luis', + 'America/Araguaina', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '694234800', + [ + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Paramaribo', + 'America/Argentina/San_Luis', + 'America/Araguaina', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '811047600', + [ + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Paramaribo', + 'America/Argentina/San_Luis', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '813553200', + [ + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Paramaribo', + 'America/Argentina/San_Luis', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '841806000', + [ + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Paramaribo', + 'America/Argentina/San_Luis', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '938660400', + [ + 'America/Belem', + 'America/Paramaribo', + 'America/Argentina/San_Luis', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '938919600', + [ + 'America/Belem', + 'America/Paramaribo', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '952056000', + [ + 'America/Belem', + 'America/Argentina/Tucuman', + 'America/Argentina/San_Juan', + 'America/Paramaribo', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '971578800', + [ + 'America/Recife', + 'America/Belem', + 'America/Argentina/Tucuman', + 'America/Argentina/San_Juan', + 'America/Paramaribo', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '972183600', + [ + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/San_Juan', + 'America/Paramaribo', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1000350000', + [ + 'America/Belem', + 'America/Argentina/Tucuman', + 'America/Argentina/San_Juan', + 'America/Paramaribo', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1033441200', + [ + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/San_Juan', + 'America/Paramaribo', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1064372400', + [ + 'America/Bahia', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/San_Juan', + 'America/Paramaribo', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1085281200', + [ + 'America/Bahia', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/San_Juan', + 'America/Paramaribo', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1085886000', + [ + 'America/Bahia', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/San_Juan', + 'America/Paramaribo', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1085972400', + [ + 'America/Bahia', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Paramaribo', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1086058800', + [ + 'America/Bahia', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Paramaribo', + 'America/Araguaina', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1214280000', + [ + 'America/Bahia', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Paramaribo', + 'America/Santarem', + 'America/Araguaina', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1224298800', + [ + 'America/Bahia', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Paramaribo', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1255233600', + [ + 'America/Bahia', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Paramaribo', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1283666400', + [ + 'America/Bahia', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Paramaribo', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Atlantic/Stanley', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1318734000', + [ + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Paramaribo', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Atlantic/Stanley', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1350788400', + [ + 'America/Bahia', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Paramaribo', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Atlantic/Stanley', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ], + [ + '1378004400', + [ + 'America/Bahia', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Maceio', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Paramaribo', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Cayenne', + 'Atlantic/Stanley', + 'Antarctica/Rothera', + 'Etc/GMT-3' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Montevideo', + 'Antarctica/Palmer' + ] + ], + [ + '323845200', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Montevideo', + 'Antarctica/Palmer', + 'America/Danmarkshavn' + ] + ], + [ + '389070000', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '420609600', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Montevideo', + 'Atlantic/Stanley', + 'America/Danmarkshavn' + ] + ], + [ + '495601200', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '536468400', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Belem', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '590036400', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '631162800', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '636519600', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '653540400', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '667796400', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/Catamarca', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '667969200', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '673588800', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/San_Juan', + 'America/Argentina/La_Rioja', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '687931200', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '694234800', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '719380800', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '811047600', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '813553200', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo', + 'America/Danmarkshavn' + ] + ], + [ + '820465200', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '841806000', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '938660400', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Araguaina', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '938919600', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Fortaleza', + 'America/Recife', + 'America/Maceio', + 'America/Araguaina', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '952056000', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Salta', + 'America/Argentina/Jujuy', + 'America/Araguaina', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '971578800', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Salta', + 'America/Argentina/Jujuy', + 'America/Araguaina', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '972183600', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Salta', + 'America/Argentina/Jujuy', + 'America/Araguaina', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1000350000', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Fortaleza', + 'America/Recife', + 'America/Argentina/Cordoba', + 'America/Maceio', + 'America/Argentina/Salta', + 'America/Argentina/Jujuy', + 'America/Araguaina', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1033441200', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Salta', + 'America/Argentina/Jujuy', + 'America/Araguaina', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1064372400', + [ + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Salta', + 'America/Argentina/Jujuy', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1087099200', + [ + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/Jujuy', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1087704000', + [ + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1090728000', + [ + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1096171200', + [ + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1200884400', + [ + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1224298800', + [ + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1318734000', + [ + 'America/Bahia', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1350788400', + [ + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Araguaina', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ], + [ + '1378004400', + [ + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Argentina/Tucuman', + 'America/Godthab', + 'America/Miquelon', + 'America/Montevideo' + ] + ] + ] + }, + '-0200' => { + 'N' => [ + [ + '0', + [ + 'Atlantic/Cape_Verde', + 'America/Scoresbysund', + 'Atlantic/South_Georgia', + 'Etc/GMT-2' + ] + ], + [ + '186120000', + [ + 'America/Scoresbysund', + 'Atlantic/South_Georgia', + 'Etc/GMT-2' + ] + ], + [ + '323841600', + [ + 'Atlantic/South_Georgia', + 'Etc/GMT-2' + ] + ], + [ + '653536800', + [ + 'Atlantic/South_Georgia', + 'America/Noronha', + 'Etc/GMT-2' + ] + ], + [ + '938656800', + [ + 'Atlantic/South_Georgia', + 'Etc/GMT-2' + ] + ], + [ + '971575200', + [ + 'Atlantic/South_Georgia', + 'America/Noronha', + 'Etc/GMT-2' + ] + ], + [ + '1000346400', + [ + 'Atlantic/South_Georgia', + 'Etc/GMT-2' + ] + ], + [ + '1033437600', + [ + 'Atlantic/South_Georgia', + 'America/Noronha', + 'Etc/GMT-2' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'America/Noronha' + ] + ], + [ + '323841600', + [ + 'America/Scoresbysund', + 'America/Noronha' + ] + ], + [ + '354679200', + [ + 'America/Noronha' + ] + ], + [ + '653536800', + [] + ], + [ + '938656800', + [ + 'America/Noronha' + ] + ], + [ + '971575200', + [] + ], + [ + '1000346400', + [ + 'America/Noronha' + ] + ] + ] + }, + '-0400' => { + 'N' => [ + [ + '0', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Asuncion', + 'America/Martinique', + 'America/Curacao', + 'America/Antigua', + 'Atlantic/Bermuda', + 'America/Port_of_Spain', + 'America/Glace_Bay', + 'America/Miquelon', + 'America/La_Paz', + 'Etc/GMT-4' + ] + ], + [ + '14400', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Asuncion', + 'America/Martinique', + 'America/Curacao', + 'America/Antigua', + 'Atlantic/Bermuda', + 'America/Port_of_Spain', + 'America/Glace_Bay', + 'America/Miquelon', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '63086400', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Asuncion', + 'America/Martinique', + 'America/Curacao', + 'America/Antigua', + 'Atlantic/Bermuda', + 'America/Port_of_Spain', + 'America/Miquelon', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '86760000', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Martinique', + 'America/Curacao', + 'America/Antigua', + 'Atlantic/Bermuda', + 'America/Port_of_Spain', + 'America/Miquelon', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '136360800', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Martinique', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/Miquelon', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '152082000', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Santo_Domingo', + 'America/Martinique', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/Miquelon', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '326001600', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Santo_Domingo', + 'America/Martinique', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '590040000', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '636519600', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Martinique', + 'America/Argentina/Jujuy', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '637383600', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Martinique', + 'America/Argentina/Jujuy', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Argentina/San_Luis', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '662698800', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Argentina/Jujuy', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Argentina/San_Luis', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '667796400', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Argentina/San_Juan', + 'America/Martinique', + 'America/Argentina/Jujuy', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '667969200', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Argentina/Cordoba', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Martinique', + 'America/Argentina/Jujuy', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '673588800', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Argentina/Cordoba', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Martinique', + 'America/Argentina/Jujuy', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '675748800', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Argentina/Cordoba', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Martinique', + 'America/Argentina/Jujuy', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '686721600', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Argentina/Cordoba', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '687931200', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '719380800', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '749188800', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '780206400', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '938664000', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '938919600', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Santarem', + 'America/Argentina/San_Luis', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '952056000', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '971582400', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '972799200', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '975823200', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1064376000', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Cuiaba', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1085281200', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Cuiaba', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1085886000', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Cuiaba', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Argentina/Ushuaia', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1085972400', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Cuiaba', + 'America/Argentina/San_Juan', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Argentina/San_Luis', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Argentina/Ushuaia', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1086058800', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Argentina/Tucuman', + 'America/Cuiaba', + 'America/Argentina/San_Juan', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1087099200', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Cuiaba', + 'America/Argentina/San_Juan', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Argentina/Catamarca', + 'America/Argentina/San_Luis', + 'America/Argentina/La_Rioja', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Ushuaia', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1087704000', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Cuiaba', + 'America/Argentina/San_Juan', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Argentina/San_Luis', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1090728000', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Cuiaba', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Argentina/Mendoza', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1096171200', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Cuiaba', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1096603200', + [ + 'America/Caracas', + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1197183600', + [ + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1214280000', + [ + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1214283600', + [ + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Rio_Branco', + 'America/Boa_Vista', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/Eirunepe', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ], + [ + '1384056000', + [ + 'America/Puerto_Rico', + 'America/Manaus', + 'America/Santo_Domingo', + 'America/Guyana', + 'America/Martinique', + 'America/Porto_Velho', + 'America/Boa_Vista', + 'America/Curacao', + 'America/Antigua', + 'America/Port_of_Spain', + 'America/La_Paz', + 'America/Blanc-Sablon', + 'Etc/GMT-4' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'America/Santiago', + 'America/Manaus', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Porto_Velho', + 'America/Barbados', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Moncton', + 'America/Halifax', + 'Atlantic/Stanley', + 'America/Pangnirtung', + 'America/Blanc-Sablon', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '14400', + [ + 'America/Santiago', + 'America/Manaus', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Porto_Velho', + 'America/Barbados', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Moncton', + 'America/Halifax', + 'Atlantic/Stanley', + 'America/Pangnirtung', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '63086400', + [ + 'America/Santiago', + 'America/Manaus', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Porto_Velho', + 'America/Barbados', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Atlantic/Stanley', + 'America/Pangnirtung', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '134017200', + [ + 'America/Santiago', + 'America/Manaus', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Porto_Velho', + 'America/Barbados', + 'America/Boa_Vista', + 'America/Santarem', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Atlantic/Stanley', + 'America/Pangnirtung', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '136360800', + [ + 'America/Santiago', + 'America/Manaus', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Porto_Velho', + 'America/Barbados', + 'America/Boa_Vista', + 'America/Santarem', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Atlantic/Stanley', + 'America/Pangnirtung', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '389070000', + [ + 'America/Santiago', + 'America/Manaus', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Porto_Velho', + 'America/Barbados', + 'America/Boa_Vista', + 'America/Santarem', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Pangnirtung', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '420609600', + [ + 'America/Santiago', + 'America/Manaus', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Porto_Velho', + 'America/Barbados', + 'America/Boa_Vista', + 'America/Santarem', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'America/Pangnirtung', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '495601200', + [ + 'America/Santiago', + 'America/Manaus', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Porto_Velho', + 'America/Barbados', + 'America/Boa_Vista', + 'America/Santarem', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Pangnirtung', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '590040000', + [ + 'America/Santiago', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Barbados', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Pangnirtung', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '749188800', + [ + 'America/Santiago', + 'America/Manaus', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Barbados', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Pangnirtung', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '780206400', + [ + 'America/Santiago', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Barbados', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Pangnirtung', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '796802400', + [ + 'America/Santiago', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Barbados', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '938664000', + [ + 'America/Santiago', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Barbados', + 'America/Boa_Vista', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '938919600', + [ + 'America/Santiago', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Cordoba', + 'America/Campo_Grande', + 'America/Argentina/Tucuman', + 'America/Argentina/Salta', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Argentina/San_Juan', + 'America/Argentina/Jujuy', + 'America/Barbados', + 'America/Boa_Vista', + 'America/Argentina/Catamarca', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Argentina/Rio_Gallegos', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Argentina/Ushuaia', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '952056000', + [ + 'America/Santiago', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Barbados', + 'America/Boa_Vista', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '971582400', + [ + 'America/Santiago', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Barbados', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '1064376000', + [ + 'America/Santiago', + 'America/Campo_Grande', + 'America/Asuncion', + 'America/Barbados', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '1096603200', + [ + 'America/Santiago', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Barbados', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '1200884400', + [ + 'America/Santiago', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Barbados', + 'America/Argentina/San_Luis', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '1255233600', + [ + 'America/Santiago', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Barbados', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'Atlantic/Stanley', + 'America/Goose_Bay', + 'America/Thule' + ] + ], + [ + '1283666400', + [ + 'America/Santiago', + 'America/Campo_Grande', + 'America/Cuiaba', + 'America/Asuncion', + 'America/Barbados', + 'Atlantic/Bermuda', + 'America/Moncton', + 'America/Glace_Bay', + 'America/Halifax', + 'Antarctica/Palmer', + 'America/Goose_Bay', + 'America/Thule' + ] + ] + ] + }, + '+0800' => { + 'N' => [ + [ + '0', + [ + 'Asia/Makassar', + 'Asia/Kuching', + 'Asia/Pontianak', + 'Asia/Brunei', + 'Antarctica/Casey', + 'Etc/GMT+8' + ] + ], + [ + '199897200', + [ + 'Asia/Makassar', + 'Asia/Kuching', + 'Asia/Pontianak', + 'Asia/Brunei', + 'Asia/Dili', + 'Antarctica/Casey', + 'Etc/GMT+8' + ] + ], + [ + '252435600', + [ + 'Asia/Makassar', + 'Asia/Kuching', + 'Asia/Pontianak', + 'Asia/Brunei', + 'Asia/Dili', + 'Asia/Choibalsan', + 'Antarctica/Casey', + 'Etc/GMT+8' + ] + ], + [ + '378664200', + [ + 'Asia/Singapore', + 'Asia/Kuala_Lumpur', + 'Asia/Makassar', + 'Asia/Kuching', + 'Asia/Pontianak', + 'Asia/Brunei', + 'Asia/Dili', + 'Asia/Choibalsan', + 'Antarctica/Casey', + 'Etc/GMT+8' + ] + ], + [ + '417974400', + [ + 'Asia/Singapore', + 'Asia/Kuala_Lumpur', + 'Asia/Makassar', + 'Asia/Kuching', + 'Asia/Pontianak', + 'Asia/Brunei', + 'Asia/Dili', + 'Antarctica/Casey', + 'Etc/GMT+8' + ] + ], + [ + '567964800', + [ + 'Asia/Singapore', + 'Asia/Kuala_Lumpur', + 'Asia/Makassar', + 'Asia/Kuching', + 'Asia/Brunei', + 'Asia/Dili', + 'Antarctica/Casey', + 'Etc/GMT+8' + ] + ], + [ + '969120000', + [ + 'Asia/Singapore', + 'Asia/Kuala_Lumpur', + 'Asia/Makassar', + 'Asia/Kuching', + 'Asia/Brunei', + 'Antarctica/Casey', + 'Etc/GMT+8' + ] + ], + [ + '1255802400', + [ + 'Asia/Singapore', + 'Asia/Kuala_Lumpur', + 'Asia/Makassar', + 'Asia/Kuching', + 'Asia/Brunei', + 'Etc/GMT+8' + ] + ], + [ + '1267714800', + [ + 'Asia/Singapore', + 'Asia/Kuala_Lumpur', + 'Asia/Makassar', + 'Asia/Kuching', + 'Asia/Brunei', + 'Antarctica/Casey', + 'Etc/GMT+8' + ] + ], + [ + '1301166000', + [ + 'Asia/Singapore', + 'Asia/Kuala_Lumpur', + 'Asia/Makassar', + 'Asia/Krasnoyarsk', + 'Asia/Kuching', + 'Asia/Brunei', + 'Antarctica/Casey', + 'Etc/GMT+8' + ] + ], + [ + '1319738400', + [ + 'Asia/Singapore', + 'Asia/Kuala_Lumpur', + 'Asia/Makassar', + 'Asia/Krasnoyarsk', + 'Asia/Kuching', + 'Asia/Brunei', + 'Etc/GMT+8' + ] + ], + [ + '1329843600', + [ + 'Asia/Singapore', + 'Asia/Kuala_Lumpur', + 'Asia/Makassar', + 'Asia/Krasnoyarsk', + 'Asia/Kuching', + 'Asia/Brunei', + 'Antarctica/Casey', + 'Etc/GMT+8' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Asia/Shanghai', + 'Asia/Hong_Kong', + 'Asia/Taipei', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Macau', + 'Asia/Irkutsk' + ] + ], + [ + '252435600', + [ + 'Asia/Shanghai', + 'Asia/Hong_Kong', + 'Asia/Taipei', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Ulaanbaatar', + 'Asia/Macau', + 'Asia/Irkutsk' + ] + ], + [ + '325956600', + [ + 'Asia/Shanghai', + 'Asia/Harbin', + 'Asia/Hong_Kong', + 'Asia/Taipei', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Ulaanbaatar', + 'Asia/Macau', + 'Asia/Irkutsk' + ] + ], + [ + '325962000', + [ + 'Asia/Shanghai', + 'Asia/Harbin', + 'Asia/Hong_Kong', + 'Asia/Chongqing', + 'Asia/Taipei', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Ulaanbaatar', + 'Asia/Macau', + 'Asia/Irkutsk' + ] + ], + [ + '325965600', + [ + 'Asia/Shanghai', + 'Asia/Harbin', + 'Asia/Hong_Kong', + 'Asia/Chongqing', + 'Asia/Taipei', + 'Asia/Urumqi', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Ulaanbaatar', + 'Asia/Macau', + 'Asia/Irkutsk' + ] + ], + [ + '325969200', + [ + 'Asia/Shanghai', + 'Asia/Harbin', + 'Asia/Hong_Kong', + 'Asia/Chongqing', + 'Asia/Taipei', + 'Asia/Urumqi', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Ulaanbaatar', + 'Asia/Macau', + 'Asia/Irkutsk', + 'Asia/Kashgar' + ] + ], + [ + '670352400', + [ + 'Asia/Shanghai', + 'Asia/Harbin', + 'Asia/Hong_Kong', + 'Asia/Chongqing', + 'Asia/Taipei', + 'Asia/Urumqi', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Ulaanbaatar', + 'Asia/Macau', + 'Asia/Irkutsk', + 'Asia/Yakutsk', + 'Asia/Khandyga', + 'Asia/Kashgar' + ] + ], + [ + '670356000', + [ + 'Asia/Shanghai', + 'Asia/Harbin', + 'Asia/Hong_Kong', + 'Asia/Chongqing', + 'Asia/Taipei', + 'Asia/Urumqi', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Ulaanbaatar', + 'Asia/Macau', + 'Asia/Yakutsk', + 'Asia/Khandyga', + 'Asia/Kashgar' + ] + ], + [ + '695757600', + [ + 'Asia/Shanghai', + 'Asia/Harbin', + 'Asia/Hong_Kong', + 'Asia/Chongqing', + 'Asia/Taipei', + 'Asia/Urumqi', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Ulaanbaatar', + 'Asia/Macau', + 'Asia/Kashgar' + ] + ], + [ + '695761200', + [ + 'Asia/Shanghai', + 'Asia/Harbin', + 'Asia/Hong_Kong', + 'Asia/Chongqing', + 'Asia/Taipei', + 'Asia/Urumqi', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Ulaanbaatar', + 'Asia/Macau', + 'Asia/Irkutsk', + 'Asia/Kashgar' + ] + ], + [ + '1206889200', + [ + 'Asia/Shanghai', + 'Asia/Harbin', + 'Asia/Hong_Kong', + 'Asia/Chongqing', + 'Asia/Taipei', + 'Asia/Urumqi', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Ulaanbaatar', + 'Asia/Macau', + 'Asia/Irkutsk', + 'Asia/Choibalsan', + 'Asia/Kashgar' + ] + ], + [ + '1301162400', + [ + 'Asia/Shanghai', + 'Asia/Harbin', + 'Asia/Hong_Kong', + 'Asia/Chongqing', + 'Asia/Taipei', + 'Asia/Urumqi', + 'Australia/Perth', + 'Asia/Manila', + 'Asia/Ulaanbaatar', + 'Asia/Macau', + 'Asia/Choibalsan', + 'Asia/Kashgar' + ] + ] + ] + }, + '+0700' => { + 'N' => [ + [ + '0', + [ + 'Asia/Jakarta', + 'Asia/Ho_Chi_Minh', + 'Asia/Bangkok', + 'Asia/Chongqing', + 'Asia/Phnom_Penh', + 'Asia/Ulaanbaatar', + 'Asia/Vientiane', + 'Antarctica/Davis', + 'Asia/Choibalsan', + 'Etc/GMT+7', + 'Indian/Christmas' + ] + ], + [ + '252435600', + [ + 'Asia/Jakarta', + 'Asia/Ho_Chi_Minh', + 'Asia/Bangkok', + 'Asia/Chongqing', + 'Asia/Phnom_Penh', + 'Asia/Vientiane', + 'Antarctica/Davis', + 'Etc/GMT+7', + 'Indian/Christmas' + ] + ], + [ + '325962000', + [ + 'Asia/Jakarta', + 'Asia/Ho_Chi_Minh', + 'Asia/Bangkok', + 'Asia/Phnom_Penh', + 'Asia/Vientiane', + 'Antarctica/Davis', + 'Etc/GMT+7', + 'Indian/Christmas' + ] + ], + [ + '567964800', + [ + 'Asia/Jakarta', + 'Asia/Ho_Chi_Minh', + 'Asia/Bangkok', + 'Asia/Phnom_Penh', + 'Asia/Pontianak', + 'Asia/Vientiane', + 'Antarctica/Davis', + 'Etc/GMT+7', + 'Indian/Christmas' + ] + ], + [ + '1255806000', + [ + 'Asia/Jakarta', + 'Asia/Ho_Chi_Minh', + 'Asia/Bangkok', + 'Asia/Phnom_Penh', + 'Asia/Pontianak', + 'Asia/Vientiane', + 'Etc/GMT+7', + 'Indian/Christmas' + ] + ], + [ + '1268251200', + [ + 'Asia/Jakarta', + 'Asia/Ho_Chi_Minh', + 'Asia/Bangkok', + 'Asia/Phnom_Penh', + 'Asia/Pontianak', + 'Asia/Vientiane', + 'Antarctica/Davis', + 'Etc/GMT+7', + 'Indian/Christmas' + ] + ], + [ + '1301169600', + [ + 'Asia/Jakarta', + 'Asia/Ho_Chi_Minh', + 'Asia/Bangkok', + 'Asia/Phnom_Penh', + 'Asia/Omsk', + 'Asia/Novokuznetsk', + 'Asia/Pontianak', + 'Asia/Vientiane', + 'Antarctica/Davis', + 'Asia/Novosibirsk', + 'Etc/GMT+7', + 'Indian/Christmas' + ] + ], + [ + '1319742000', + [ + 'Asia/Jakarta', + 'Asia/Ho_Chi_Minh', + 'Asia/Bangkok', + 'Asia/Phnom_Penh', + 'Asia/Omsk', + 'Asia/Novokuznetsk', + 'Asia/Pontianak', + 'Asia/Vientiane', + 'Asia/Novosibirsk', + 'Etc/GMT+7', + 'Indian/Christmas' + ] + ], + [ + '1329854400', + [ + 'Asia/Jakarta', + 'Asia/Ho_Chi_Minh', + 'Asia/Bangkok', + 'Asia/Phnom_Penh', + 'Asia/Omsk', + 'Asia/Novokuznetsk', + 'Asia/Pontianak', + 'Asia/Vientiane', + 'Antarctica/Davis', + 'Asia/Novosibirsk', + 'Etc/GMT+7', + 'Indian/Christmas' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Asia/Krasnoyarsk', + 'Asia/Novokuznetsk', + 'Asia/Novosibirsk' + ] + ], + [ + '252439200', + [ + 'Asia/Krasnoyarsk', + 'Asia/Novokuznetsk', + 'Asia/Hovd', + 'Asia/Novosibirsk' + ] + ], + [ + '670356000', + [ + 'Asia/Krasnoyarsk', + 'Asia/Irkutsk', + 'Asia/Novokuznetsk', + 'Asia/Hovd', + 'Asia/Novosibirsk' + ] + ], + [ + '670359600', + [ + 'Asia/Irkutsk', + 'Asia/Hovd' + ] + ], + [ + '695761200', + [ + 'Asia/Hovd' + ] + ], + [ + '695764800', + [ + 'Asia/Krasnoyarsk', + 'Asia/Novokuznetsk', + 'Asia/Hovd', + 'Asia/Novosibirsk' + ] + ], + [ + '738090000', + [ + 'Asia/Krasnoyarsk', + 'Asia/Novokuznetsk', + 'Asia/Hovd' + ] + ], + [ + '1269716400', + [ + 'Asia/Krasnoyarsk', + 'Asia/Hovd' + ] + ], + [ + '1301166000', + [ + 'Asia/Hovd' + ] + ] + ] + }, + '+0845' => { + 'Y' => [ + [ + '0', + [ + 'Australia/Eucla' + ] + ] + ] + }, + '+0100' => { + 'N' => [ + [ + '0', + [ + 'Europe/London', + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Europe/Berlin', + 'Africa/Luanda', + 'Africa/Douala', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Africa/Brazzaville', + 'Europe/Dublin', + 'Europe/Prague', + 'Europe/Brussels', + 'Africa/Ndjamena', + 'Europe/Stockholm', + 'Africa/Niamey', + 'Europe/Oslo', + 'Africa/Libreville', + 'Africa/Bangui', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Lisbon', + 'Europe/Zurich', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Andorra', + 'Europe/Gibraltar', + 'Europe/Amsterdam', + 'Etc/GMT+1' + ] + ], + [ + '57722400', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Europe/Berlin', + 'Africa/Luanda', + 'Africa/Douala', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Africa/Brazzaville', + 'Europe/Prague', + 'Europe/Brussels', + 'Africa/Ndjamena', + 'Europe/Stockholm', + 'Africa/Niamey', + 'Europe/Oslo', + 'Africa/Libreville', + 'Africa/Bangui', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Lisbon', + 'Europe/Zurich', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Andorra', + 'Europe/Gibraltar', + 'Europe/Amsterdam', + 'Etc/GMT+1' + ] + ], + [ + '212544000', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Europe/Berlin', + 'Africa/Luanda', + 'Africa/Douala', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Africa/Brazzaville', + 'Europe/Prague', + 'Europe/Brussels', + 'Africa/Ndjamena', + 'Europe/Stockholm', + 'Africa/Niamey', + 'Europe/Oslo', + 'Africa/Libreville', + 'Africa/Bangui', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Zurich', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Andorra', + 'Europe/Gibraltar', + 'Europe/Amsterdam', + 'Etc/GMT+1' + ] + ], + [ + '220921200', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Europe/Berlin', + 'Africa/Luanda', + 'Africa/Douala', + 'Europe/Belgrade', + 'Africa/Brazzaville', + 'Europe/Prague', + 'Africa/Ndjamena', + 'Europe/Stockholm', + 'Africa/Niamey', + 'Europe/Oslo', + 'Africa/Libreville', + 'Africa/Bangui', + 'Europe/Copenhagen', + 'Europe/Zurich', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Andorra', + 'Europe/Gibraltar', + 'Etc/GMT+1' + ] + ], + [ + '283993200', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Europe/Berlin', + 'Africa/Luanda', + 'Africa/Douala', + 'Europe/Belgrade', + 'Africa/Brazzaville', + 'Africa/Ndjamena', + 'Europe/Stockholm', + 'Africa/Niamey', + 'Europe/Oslo', + 'Africa/Libreville', + 'Africa/Bangui', + 'Europe/Copenhagen', + 'Europe/Zurich', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Andorra', + 'Europe/Gibraltar', + 'Etc/GMT+1' + ] + ], + [ + '315529200', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Africa/Luanda', + 'Africa/Douala', + 'Europe/Belgrade', + 'Africa/Brazzaville', + 'Africa/Ndjamena', + 'Africa/Niamey', + 'Africa/Libreville', + 'Africa/Bangui', + 'Europe/Zurich', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Andorra', + 'Europe/Gibraltar', + 'Etc/GMT+1' + ] + ], + [ + '347151600', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Africa/Luanda', + 'Africa/Douala', + 'Europe/Belgrade', + 'Africa/Brazzaville', + 'Africa/Ndjamena', + 'Africa/Niamey', + 'Africa/Libreville', + 'Africa/Bangui', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Andorra', + 'Europe/Gibraltar', + 'Etc/GMT+1' + ] + ], + [ + '357523200', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Africa/Luanda', + 'Africa/Algiers', + 'Africa/Douala', + 'Europe/Belgrade', + 'Africa/Brazzaville', + 'Africa/Ndjamena', + 'Africa/Niamey', + 'Africa/Libreville', + 'Africa/Bangui', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Andorra', + 'Europe/Gibraltar', + 'Etc/GMT+1' + ] + ], + [ + '378687600', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Africa/Luanda', + 'Africa/Algiers', + 'Africa/Douala', + 'Europe/Belgrade', + 'Africa/Brazzaville', + 'Africa/Ndjamena', + 'Africa/Niamey', + 'Africa/Libreville', + 'Africa/Bangui', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Andorra', + 'Etc/GMT+1' + ] + ], + [ + '407199600', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Africa/Luanda', + 'Africa/Algiers', + 'Africa/Douala', + 'Africa/Brazzaville', + 'Africa/Ndjamena', + 'Africa/Niamey', + 'Africa/Libreville', + 'Africa/Bangui', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Andorra', + 'Etc/GMT+1' + ] + ], + [ + '448243200', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Africa/Casablanca', + 'Africa/Luanda', + 'Africa/Algiers', + 'Africa/Douala', + 'Africa/Brazzaville', + 'Africa/Ndjamena', + 'Africa/Niamey', + 'Africa/Libreville', + 'Africa/Bangui', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Etc/GMT+1' + ] + ], + [ + '481078800', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Africa/Casablanca', + 'Africa/Luanda', + 'Africa/Algiers', + 'Africa/Douala', + 'Africa/Brazzaville', + 'Africa/Ndjamena', + 'Africa/Niamey', + 'Africa/Libreville', + 'Africa/Bangui', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Africa/Ceuta', + 'Etc/GMT+1' + ] + ], + [ + '504918000', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Africa/Luanda', + 'Africa/Algiers', + 'Africa/Douala', + 'Africa/Brazzaville', + 'Africa/Ndjamena', + 'Africa/Niamey', + 'Africa/Libreville', + 'Africa/Bangui', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Etc/GMT+1' + ] + ], + [ + '646786800', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Africa/Luanda', + 'Africa/Algiers', + 'Africa/Douala', + 'Africa/Brazzaville', + 'Africa/Ndjamena', + 'Africa/Niamey', + 'Africa/Libreville', + 'Africa/Bangui', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Europe/Uzhgorod', + 'Etc/GMT+1' + ] + ], + [ + '670384800', + [ + 'Africa/Lagos', + 'Africa/Kinshasa', + 'Africa/Luanda', + 'Africa/Algiers', + 'Africa/Douala', + 'Africa/Brazzaville', + 'Africa/Ndjamena', + 'Africa/Niamey', + 'Africa/Libreville', + 'Africa/Bangui', + 'Africa/Porto-Novo', + 'Africa/Malabo', + 'Etc/GMT+1' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Monaco' + ] + ], + [ + '220921200', + [ + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Brussels', + 'Europe/Luxembourg', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Monaco', + 'Europe/Amsterdam' + ] + ], + [ + '246240000', + [ + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Africa/Algiers', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Brussels', + 'Europe/Luxembourg', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Monaco', + 'Europe/Amsterdam' + ] + ], + [ + '283993200', + [ + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Africa/Algiers', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Luxembourg', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Monaco', + 'Europe/Amsterdam' + ] + ], + [ + '309740400', + [ + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Luxembourg', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Monaco', + 'Europe/Amsterdam' + ] + ], + [ + '315529200', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Monaco', + 'Europe/Amsterdam' + ] + ], + [ + '347151600', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Europe/Monaco', + 'Europe/Amsterdam' + ] + ], + [ + '378684000', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Prague', + 'Europe/Brussels', + 'Africa/Tripoli', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Europe/Monaco', + 'Europe/Amsterdam' + ] + ], + [ + '378687600', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Prague', + 'Europe/Brussels', + 'Africa/Tripoli', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '407199600', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Africa/Tripoli', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '481078800', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Africa/Tripoli', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Europe/Andorra', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '504918000', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Africa/Tripoli', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '641775600', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '717555600', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Lisbon', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '765324000', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Lisbon', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Africa/Windhoek', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '828234000', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Africa/Windhoek', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '844034400', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Africa/Tripoli', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Africa/Windhoek', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '875919600', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Africa/Windhoek', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '891133200', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Vilnius', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Africa/Windhoek', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '941331600', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Africa/Windhoek', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '1352505600', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Africa/Tripoli', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Africa/Windhoek', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ], + [ + '1382662800', + [ + 'Europe/Berlin', + 'Europe/Madrid', + 'Europe/Rome', + 'Africa/Tunis', + 'Europe/Paris', + 'Europe/Vienna', + 'Europe/Budapest', + 'Europe/Warsaw', + 'Europe/Belgrade', + 'Europe/Prague', + 'Europe/Brussels', + 'Europe/Stockholm', + 'Europe/Oslo', + 'Europe/Luxembourg', + 'Europe/Copenhagen', + 'Europe/Tirane', + 'Europe/Malta', + 'Europe/Zurich', + 'Africa/Windhoek', + 'Europe/Andorra', + 'Africa/Ceuta', + 'Europe/Monaco', + 'Europe/Gibraltar', + 'Europe/Amsterdam' + ] + ] + ] + }, + '+1400' => { + 'N' => [ + [ + '0', + [ + 'Etc/GMT+14' + ] + ], + [ + '788954400', + [ + 'Etc/GMT+14', + 'Pacific/Kiritimati' + ] + ] + ] + }, + '+0430' => { + 'N' => [ + [ + '0', + [ + 'Asia/Kabul' + ] + ] + ] + }, + '+0830' => { + 'N' => [ + [ + '0', + [ + 'Asia/Harbin' + ] + ] + ] + }, + '+0530' => { + 'N' => [ + [ + '0', + [ + 'Asia/Kolkata', + 'Asia/Kathmandu', + 'Asia/Colombo', + 'Asia/Thimphu' + ] + ], + [ + '504901800', + [ + 'Asia/Kolkata', + 'Asia/Colombo', + 'Asia/Thimphu' + ] + ], + [ + '560025000', + [ + 'Asia/Kolkata', + 'Asia/Colombo' + ] + ], + [ + '832962600', + [ + 'Asia/Kolkata' + ] + ], + [ + '1145039400', + [ + 'Asia/Kolkata', + 'Asia/Colombo' + ] + ] + ] + }, + '-1100' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Apia', + 'Pacific/Pago_Pago', + 'Pacific/Midway', + 'Etc/GMT-11', + 'Pacific/Fakaofo' + ] + ], + [ + '276089400', + [ + 'Pacific/Apia', + 'Pacific/Pago_Pago', + 'Pacific/Midway', + 'Pacific/Niue', + 'Etc/GMT-11', + 'Pacific/Fakaofo' + ] + ], + [ + '307627200', + [ + 'Pacific/Apia', + 'Pacific/Pago_Pago', + 'Pacific/Midway', + 'Pacific/Niue', + 'Etc/GMT-11', + 'Pacific/Enderbury', + 'Pacific/Fakaofo' + ] + ], + [ + '788958000', + [ + 'Pacific/Apia', + 'Pacific/Pago_Pago', + 'Pacific/Midway', + 'Pacific/Niue', + 'Etc/GMT-11', + 'Pacific/Fakaofo' + ] + ], + [ + '1325242800', + [ + 'Pacific/Pago_Pago', + 'Pacific/Midway', + 'Pacific/Niue', + 'Etc/GMT-11' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'America/Nome', + 'America/Adak' + ] + ] + ] + }, + '+0900' => { + 'N' => [ + [ + '0', + [ + 'Asia/Tokyo', + 'Asia/Pyongyang', + 'Asia/Dili', + 'Asia/Jayapura', + 'Pacific/Palau', + 'Etc/GMT+9' + ] + ], + [ + '199897200', + [ + 'Asia/Tokyo', + 'Asia/Pyongyang', + 'Asia/Jayapura', + 'Pacific/Palau', + 'Etc/GMT+9' + ] + ], + [ + '969120000', + [ + 'Asia/Tokyo', + 'Asia/Pyongyang', + 'Asia/Dili', + 'Asia/Jayapura', + 'Pacific/Palau', + 'Etc/GMT+9' + ] + ], + [ + '1301162400', + [ + 'Asia/Tokyo', + 'Asia/Pyongyang', + 'Asia/Irkutsk', + 'Asia/Dili', + 'Asia/Jayapura', + 'Pacific/Palau', + 'Etc/GMT+9' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Asia/Seoul', + 'Asia/Yakutsk', + 'Asia/Ust-Nera', + 'Asia/Khandyga' + ] + ], + [ + '354898800', + [ + 'Asia/Seoul', + 'Asia/Yakutsk', + 'Asia/Khandyga' + ] + ], + [ + '417974400', + [ + 'Asia/Seoul', + 'Asia/Yakutsk', + 'Asia/Choibalsan', + 'Asia/Khandyga' + ] + ], + [ + '670348800', + [ + 'Asia/Seoul', + 'Asia/Vladivostok', + 'Asia/Yakutsk', + 'Asia/Choibalsan', + 'Asia/Khandyga' + ] + ], + [ + '670352400', + [ + 'Asia/Seoul', + 'Asia/Vladivostok', + 'Asia/Choibalsan' + ] + ], + [ + '695754000', + [ + 'Asia/Seoul', + 'Asia/Choibalsan' + ] + ], + [ + '695757600', + [ + 'Asia/Seoul', + 'Asia/Yakutsk', + 'Asia/Choibalsan', + 'Asia/Khandyga' + ] + ], + [ + '1072882800', + [ + 'Asia/Seoul', + 'Asia/Yakutsk', + 'Asia/Choibalsan' + ] + ], + [ + '1206889200', + [ + 'Asia/Seoul', + 'Asia/Yakutsk' + ] + ], + [ + '1301158800', + [ + 'Asia/Seoul' + ] + ] + ] + }, + '+1300' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Tongatapu', + 'Etc/GMT+13' + ] + ], + [ + '788958000', + [ + 'Pacific/Tongatapu', + 'Etc/GMT+13', + 'Pacific/Enderbury' + ] + ], + [ + '915102000', + [ + 'Etc/GMT+13', + 'Pacific/Enderbury' + ] + ], + [ + '1325242800', + [ + 'Pacific/Apia', + 'Etc/GMT+13', + 'Pacific/Enderbury', + 'Pacific/Fakaofo' + ] + ], + [ + '1333206000', + [ + 'Etc/GMT+13', + 'Pacific/Enderbury', + 'Pacific/Fakaofo' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Asia/Anadyr' + ] + ], + [ + '386420400', + [] + ], + [ + '915102000', + [ + 'Pacific/Tongatapu' + ] + ], + [ + '1333206000', + [ + 'Pacific/Tongatapu', + 'Pacific/Apia' + ] + ] + ] + }, + '-1030' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Rarotonga' + ] + ] + ] + }, + '-0930' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Marquesas' + ] + ] + ] + }, + '-0800' => { + 'N' => [ + [ + '0', + [ + 'America/Tijuana', + 'America/Hermosillo', + 'America/Mazatlan', + 'America/Santa_Isabel', + 'America/Bahia_Banderas', + 'Etc/GMT-8' + ] + ], + [ + '28800', + [ + 'America/Tijuana', + 'America/Santa_Isabel', + 'Etc/GMT-8' + ] + ], + [ + '189331200', + [ + 'Etc/GMT-8' + ] + ], + [ + '436356000', + [ + 'America/Metlakatla', + 'Etc/GMT-8' + ] + ], + [ + '893665800', + [ + 'America/Metlakatla', + 'Pacific/Pitcairn', + 'Etc/GMT-8' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'America/Los_Angeles', + 'America/Vancouver', + 'America/Juneau', + 'America/Dawson_Creek', + 'America/Whitehorse', + 'America/Sitka', + 'America/Inuvik', + 'America/Metlakatla' + ] + ], + [ + '84016800', + [ + 'America/Los_Angeles', + 'America/Vancouver', + 'America/Juneau', + 'America/Whitehorse', + 'America/Sitka', + 'America/Inuvik', + 'America/Metlakatla' + ] + ], + [ + '120646800', + [ + 'America/Los_Angeles', + 'America/Vancouver', + 'America/Juneau', + 'America/Whitehorse', + 'America/Sitka', + 'America/Dawson', + 'America/Inuvik', + 'America/Metlakatla' + ] + ], + [ + '189331200', + [ + 'America/Los_Angeles', + 'America/Tijuana', + 'America/Vancouver', + 'America/Santa_Isabel', + 'America/Juneau', + 'America/Whitehorse', + 'America/Sitka', + 'America/Dawson', + 'America/Inuvik', + 'America/Metlakatla' + ] + ], + [ + '294228000', + [ + 'America/Los_Angeles', + 'America/Tijuana', + 'America/Vancouver', + 'America/Santa_Isabel', + 'America/Juneau', + 'America/Whitehorse', + 'America/Sitka', + 'America/Dawson', + 'America/Metlakatla' + ] + ], + [ + '325677600', + [ + 'America/Los_Angeles', + 'America/Tijuana', + 'America/Vancouver', + 'America/Santa_Isabel', + 'America/Whitehorse', + 'America/Sitka', + 'America/Dawson', + 'America/Metlakatla' + ] + ], + [ + '341406000', + [ + 'America/Los_Angeles', + 'America/Tijuana', + 'America/Vancouver', + 'America/Santa_Isabel', + 'America/Juneau', + 'America/Whitehorse', + 'America/Sitka', + 'America/Dawson', + 'America/Metlakatla' + ] + ], + [ + '436356000', + [ + 'America/Los_Angeles', + 'America/Tijuana', + 'America/Vancouver', + 'America/Santa_Isabel', + 'America/Whitehorse', + 'America/Dawson' + ] + ] + ] + }, + '+0200' => { + 'N' => [ + [ + '0', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2', + 'Europe/Sofia' + ] + ], + [ + '291762000', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '378684000', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '606870000', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Kigali', + 'Europe/Riga', + 'Africa/Blantyre', + 'Europe/Tallinn', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '622598400', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '641775600', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '641941200', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Europe/Chisinau', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '646786800', + [ + 'Africa/Johannesburg', + 'Europe/Kiev', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Europe/Chisinau', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2', + 'Europe/Simferopol' + ] + ], + [ + '662680800', + [ + 'Africa/Johannesburg', + 'Europe/Kiev', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2', + 'Europe/Simferopol' + ] + ], + [ + '670374000', + [ + 'Africa/Johannesburg', + 'Europe/Kiev', + 'Europe/Minsk', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Europe/Vilnius', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2', + 'Europe/Simferopol' + ] + ], + [ + '670384800', + [ + 'Africa/Johannesburg', + 'Europe/Kiev', + 'Europe/Minsk', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Europe/Vilnius', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Europe/Uzhgorod', + 'Africa/Mbabane', + 'Etc/GMT+2', + 'Europe/Simferopol' + ] + ], + [ + '686102400', + [ + 'Africa/Johannesburg', + 'Europe/Kiev', + 'Europe/Minsk', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Europe/Uzhgorod', + 'Africa/Mbabane', + 'Etc/GMT+2', + 'Europe/Simferopol' + ] + ], + [ + '694216800', + [ + 'Africa/Johannesburg', + 'Europe/Minsk', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '717544800', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Windhoek', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '765324000', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '844034400', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '875919600', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '883605600', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Europe/Vilnius', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '891133200', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '941331600', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Europe/Vilnius', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '941407200', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Europe/Vilnius', + 'Europe/Tallinn', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '951775200', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Europe/Riga', + 'Africa/Blantyre', + 'Europe/Vilnius', + 'Europe/Tallinn', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '978386400', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Europe/Vilnius', + 'Europe/Tallinn', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1014242400', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Europe/Vilnius', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1041372000', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1219960800', + [ + 'Africa/Johannesburg', + 'Asia/Gaza', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1220220000', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1262296800', + [ + 'Africa/Johannesburg', + 'Asia/Gaza', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1269640860', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1301187600', + [ + 'Europe/Istanbul', + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1301274000', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1312149600', + [ + 'Africa/Johannesburg', + 'Asia/Gaza', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1325368800', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1352505600', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ], + [ + '1382662800', + [ + 'Africa/Johannesburg', + 'Africa/Harare', + 'Africa/Lubumbashi', + 'Africa/Lusaka', + 'Africa/Maputo', + 'Africa/Tripoli', + 'Africa/Kigali', + 'Africa/Blantyre', + 'Africa/Bujumbura', + 'Africa/Maseru', + 'Africa/Gaborone', + 'Africa/Mbabane', + 'Etc/GMT+2' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Asia/Jerusalem', + 'Europe/Athens', + 'Europe/Helsinki', + 'Asia/Nicosia', + 'Asia/Hebron' + ] + ], + [ + '277250400', + [ + 'Africa/Cairo', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Asia/Jerusalem', + 'Europe/Athens', + 'Europe/Helsinki', + 'Asia/Nicosia', + 'Asia/Hebron' + ] + ], + [ + '291762000', + [ + 'Africa/Cairo', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Asia/Jerusalem', + 'Europe/Athens', + 'Europe/Helsinki', + 'Asia/Nicosia', + 'Asia/Hebron', + 'Europe/Sofia' + ] + ], + [ + '482792400', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Asia/Jerusalem', + 'Europe/Athens', + 'Europe/Helsinki', + 'Asia/Nicosia', + 'Asia/Hebron', + 'Europe/Sofia' + ] + ], + [ + '622598400', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Helsinki', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Asia/Hebron', + 'Europe/Sofia' + ] + ], + [ + '662680800', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Asia/Hebron', + 'Europe/Sofia' + ] + ], + [ + '670374000', + [ + 'Europe/Istanbul', + 'Europe/Moscow', + 'Africa/Cairo', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Europe/Samara', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Asia/Hebron', + 'Europe/Sofia' + ] + ], + [ + '686102400', + [ + 'Europe/Istanbul', + 'Europe/Moscow', + 'Africa/Cairo', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Asia/Hebron', + 'Europe/Sofia' + ] + ], + [ + '694216800', + [ + 'Europe/Istanbul', + 'Europe/Moscow', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '695779200', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '717544800', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '767743200', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Sofia' + ] + ], + [ + '859683600', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '883605600', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '941407200', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Africa/Khartoum', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Kaliningrad', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '947930400', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Kaliningrad', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '951775200', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Kaliningrad', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '978386400', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Kaliningrad', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1014242400', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1041372000', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1219960800', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1220220000', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1262296800', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1269640860', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Europe/Minsk', + 'Asia/Gaza', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Kaliningrad', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1301184000', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1301187600', + [ + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1301274000', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1312149600', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1325368800', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Asia/Amman', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ], + [ + '1351202400', + [ + 'Europe/Istanbul', + 'Africa/Cairo', + 'Europe/Kiev', + 'Asia/Beirut', + 'Europe/Bucharest', + 'Asia/Gaza', + 'Asia/Damascus', + 'Europe/Zaporozhye', + 'Asia/Jerusalem', + 'Europe/Riga', + 'Europe/Athens', + 'Europe/Chisinau', + 'Europe/Helsinki', + 'Europe/Vilnius', + 'Europe/Tallinn', + 'Asia/Nicosia', + 'Europe/Uzhgorod', + 'Asia/Hebron', + 'Europe/Simferopol', + 'Europe/Sofia' + ] + ] + ] + }, + '+1130' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Nauru', + 'Pacific/Norfolk' + ] + ], + [ + '294323400', + [ + 'Pacific/Norfolk' + ] + ] + ] + }, + '+1100' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Guadalcanal', + 'Etc/GMT+11', + 'Pacific/Pohnpei' + ] + ], + [ + '915105600', + [ + 'Pacific/Guadalcanal', + 'Pacific/Kosrae', + 'Etc/GMT+11', + 'Pacific/Pohnpei' + ] + ], + [ + '1255802400', + [ + 'Pacific/Guadalcanal', + 'Pacific/Kosrae', + 'Antarctica/Casey', + 'Etc/GMT+11', + 'Pacific/Pohnpei' + ] + ], + [ + '1267714800', + [ + 'Pacific/Guadalcanal', + 'Pacific/Kosrae', + 'Etc/GMT+11', + 'Pacific/Pohnpei' + ] + ], + [ + '1270314000', + [ + 'Pacific/Guadalcanal', + 'Pacific/Kosrae', + 'Antarctica/Macquarie', + 'Etc/GMT+11', + 'Pacific/Pohnpei' + ] + ], + [ + '1301155200', + [ + 'Asia/Sakhalin', + 'Asia/Vladivostok', + 'Pacific/Guadalcanal', + 'Asia/Khandyga', + 'Pacific/Kosrae', + 'Antarctica/Macquarie', + 'Etc/GMT+11', + 'Pacific/Pohnpei' + ] + ], + [ + '1315828800', + [ + 'Asia/Sakhalin', + 'Asia/Vladivostok', + 'Pacific/Guadalcanal', + 'Asia/Ust-Nera', + 'Asia/Khandyga', + 'Pacific/Kosrae', + 'Antarctica/Macquarie', + 'Etc/GMT+11', + 'Pacific/Pohnpei' + ] + ], + [ + '1315832400', + [ + 'Asia/Sakhalin', + 'Asia/Vladivostok', + 'Pacific/Guadalcanal', + 'Asia/Ust-Nera', + 'Pacific/Kosrae', + 'Antarctica/Macquarie', + 'Etc/GMT+11', + 'Pacific/Pohnpei' + ] + ], + [ + '1319738400', + [ + 'Asia/Sakhalin', + 'Asia/Vladivostok', + 'Pacific/Guadalcanal', + 'Asia/Ust-Nera', + 'Pacific/Kosrae', + 'Antarctica/Casey', + 'Antarctica/Macquarie', + 'Etc/GMT+11', + 'Pacific/Pohnpei' + ] + ], + [ + '1329843600', + [ + 'Asia/Sakhalin', + 'Asia/Vladivostok', + 'Pacific/Guadalcanal', + 'Asia/Ust-Nera', + 'Pacific/Kosrae', + 'Antarctica/Macquarie', + 'Etc/GMT+11', + 'Pacific/Pohnpei' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Asia/Sakhalin', + 'Asia/Magadan', + 'Pacific/Noumea', + 'Pacific/Efate' + ] + ], + [ + '354898800', + [ + 'Asia/Sakhalin', + 'Asia/Magadan', + 'Pacific/Noumea', + 'Asia/Ust-Nera', + 'Pacific/Efate' + ] + ], + [ + '670341600', + [ + 'Asia/Sakhalin', + 'Asia/Kamchatka', + 'Asia/Magadan', + 'Pacific/Noumea', + 'Asia/Ust-Nera', + 'Pacific/Efate', + 'Asia/Anadyr' + ] + ], + [ + '670345200', + [ + 'Asia/Kamchatka', + 'Pacific/Noumea', + 'Pacific/Efate', + 'Asia/Anadyr' + ] + ], + [ + '695746800', + [ + 'Pacific/Noumea', + 'Pacific/Efate' + ] + ], + [ + '695750400', + [ + 'Asia/Sakhalin', + 'Asia/Magadan', + 'Pacific/Noumea', + 'Asia/Ust-Nera', + 'Pacific/Efate' + ] + ], + [ + '859647600', + [ + 'Asia/Magadan', + 'Pacific/Noumea', + 'Asia/Ust-Nera', + 'Pacific/Efate' + ] + ], + [ + '1269698400', + [ + 'Asia/Kamchatka', + 'Asia/Magadan', + 'Pacific/Noumea', + 'Asia/Ust-Nera', + 'Pacific/Efate', + 'Asia/Anadyr' + ] + ], + [ + '1301151600', + [ + 'Pacific/Noumea', + 'Pacific/Efate' + ] + ] + ] + }, + '+1030' => { + 'Y' => [ + [ + '352216800', + [ + 'Australia/Lord_Howe' + ] + ] + ] + }, + '-0345' => { + 'N' => [ + [ + '0', + [ + 'America/Guyana' + ] + ] + ] + }, + '+0330' => { + 'N' => [ + [ + '0', + [ + 'Asia/Tehran' + ] + ] + ], + 'Y' => [ + [ + '283982400', + [ + 'Asia/Tehran' + ] + ] + ] + }, + '-1040' => { + 'N' => [ + [ + '0', + [ + 'Pacific/Kiritimati' + ] + ] + ] + }, + '+0545' => { + 'N' => [ + [ + '504901800', + [ + 'Asia/Kathmandu' + ] + ] + ] + }, + '-0430' => { + 'N' => [ + [ + '1197183600', + [ + 'America/Caracas' + ] + ] + ] + }, + '+1000' => { + 'N' => [ + [ + '0', + [ + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Brisbane', + 'Pacific/Port_Moresby', + 'Pacific/Guam', + 'Pacific/Chuuk', + 'Australia/Lord_Howe', + 'Australia/Currie', + 'Antarctica/DumontDUrville', + 'Australia/Lindeman', + 'Etc/GMT+10', + 'Pacific/Saipan' + ] + ], + [ + '31500000', + [ + 'Pacific/Port_Moresby', + 'Pacific/Guam', + 'Pacific/Chuuk', + 'Australia/Lord_Howe', + 'Australia/Currie', + 'Antarctica/DumontDUrville', + 'Etc/GMT+10', + 'Pacific/Saipan' + ] + ], + [ + '47138400', + [ + 'Pacific/Port_Moresby', + 'Pacific/Guam', + 'Pacific/Chuuk', + 'Australia/Lord_Howe', + 'Antarctica/DumontDUrville', + 'Etc/GMT+10', + 'Pacific/Saipan' + ] + ], + [ + '352216800', + [ + 'Pacific/Port_Moresby', + 'Pacific/Guam', + 'Pacific/Chuuk', + 'Antarctica/DumontDUrville', + 'Etc/GMT+10', + 'Pacific/Saipan' + ] + ], + [ + '1301158800', + [ + 'Pacific/Port_Moresby', + 'Asia/Yakutsk', + 'Pacific/Guam', + 'Pacific/Chuuk', + 'Antarctica/DumontDUrville', + 'Etc/GMT+10', + 'Pacific/Saipan' + ] + ], + [ + '1315832400', + [ + 'Pacific/Port_Moresby', + 'Asia/Yakutsk', + 'Pacific/Guam', + 'Pacific/Chuuk', + 'Asia/Khandyga', + 'Antarctica/DumontDUrville', + 'Etc/GMT+10', + 'Pacific/Saipan' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Asia/Vladivostok', + 'Australia/Hobart', + 'Antarctica/Macquarie' + ] + ], + [ + '31500000', + [ + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Brisbane', + 'Asia/Vladivostok', + 'Australia/Hobart', + 'Antarctica/Macquarie', + 'Australia/Lindeman' + ] + ], + [ + '47138400', + [ + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Brisbane', + 'Asia/Vladivostok', + 'Australia/Hobart', + 'Australia/Currie', + 'Antarctica/Macquarie', + 'Australia/Lindeman' + ] + ], + [ + '670345200', + [ + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Brisbane', + 'Asia/Sakhalin', + 'Asia/Vladivostok', + 'Australia/Hobart', + 'Asia/Magadan', + 'Asia/Ust-Nera', + 'Australia/Currie', + 'Antarctica/Macquarie', + 'Australia/Lindeman' + ] + ], + [ + '670348800', + [ + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Brisbane', + 'Asia/Sakhalin', + 'Australia/Hobart', + 'Asia/Magadan', + 'Asia/Ust-Nera', + 'Australia/Currie', + 'Antarctica/Macquarie', + 'Australia/Lindeman' + ] + ], + [ + '695750400', + [ + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Brisbane', + 'Australia/Hobart', + 'Australia/Currie', + 'Antarctica/Macquarie', + 'Australia/Lindeman' + ] + ], + [ + '695754000', + [ + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Brisbane', + 'Asia/Vladivostok', + 'Australia/Hobart', + 'Australia/Currie', + 'Antarctica/Macquarie', + 'Australia/Lindeman' + ] + ], + [ + '859647600', + [ + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Brisbane', + 'Asia/Sakhalin', + 'Asia/Vladivostok', + 'Australia/Hobart', + 'Australia/Currie', + 'Antarctica/Macquarie', + 'Australia/Lindeman' + ] + ], + [ + '1072882800', + [ + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Brisbane', + 'Asia/Sakhalin', + 'Asia/Vladivostok', + 'Australia/Hobart', + 'Asia/Khandyga', + 'Australia/Currie', + 'Antarctica/Macquarie', + 'Australia/Lindeman' + ] + ], + [ + '1270314000', + [ + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Brisbane', + 'Asia/Sakhalin', + 'Asia/Vladivostok', + 'Australia/Hobart', + 'Asia/Khandyga', + 'Australia/Currie', + 'Australia/Lindeman' + ] + ], + [ + '1301155200', + [ + 'Australia/Sydney', + 'Australia/Melbourne', + 'Australia/Brisbane', + 'Australia/Hobart', + 'Australia/Currie', + 'Australia/Lindeman' + ] + ] + ] + }, + '+0000' => { + 'N' => [ + [ + '0', + [ + 'Africa/Abidjan', + 'Africa/Dakar', + 'Africa/Accra', + 'Africa/Bamako', + 'Africa/Conakry', + 'Africa/Ouagadougou', + 'Africa/Lome', + 'Africa/Nouakchott', + 'Africa/Freetown', + 'Africa/Sao_Tome', + 'Atlantic/Reykjavik', + 'Atlantic/Faroe', + 'Africa/Banjul', + 'Atlantic/St_Helena', + 'Antarctica/Rothera', + 'Atlantic/Canary', + 'Etc/UTC' + ] + ], + [ + '73529070', + [ + 'Africa/Abidjan', + 'Africa/Dakar', + 'Africa/Accra', + 'Africa/Bamako', + 'Africa/Conakry', + 'Africa/Ouagadougou', + 'Africa/Monrovia', + 'Africa/Lome', + 'Africa/Nouakchott', + 'Africa/Freetown', + 'Africa/Sao_Tome', + 'Atlantic/Reykjavik', + 'Atlantic/Faroe', + 'Africa/Banjul', + 'Atlantic/St_Helena', + 'Antarctica/Rothera', + 'Atlantic/Canary', + 'Etc/UTC' + ] + ], + [ + '157770000', + [ + 'Africa/Abidjan', + 'Africa/Dakar', + 'Africa/Accra', + 'Africa/Bamako', + 'Africa/Conakry', + 'Africa/Ouagadougou', + 'Africa/Monrovia', + 'Africa/Lome', + 'Africa/Nouakchott', + 'Africa/Freetown', + 'Africa/Sao_Tome', + 'Atlantic/Reykjavik', + 'Atlantic/Faroe', + 'Africa/Banjul', + 'Atlantic/St_Helena', + 'Africa/Bissau', + 'Antarctica/Rothera', + 'Atlantic/Canary', + 'Etc/UTC' + ] + ], + [ + '218246400', + [ + 'Africa/Abidjan', + 'Africa/Dakar', + 'Africa/Accra', + 'Africa/Bamako', + 'Africa/Conakry', + 'Africa/Ouagadougou', + 'Africa/Monrovia', + 'Africa/Lome', + 'Africa/Nouakchott', + 'Africa/Freetown', + 'Africa/Sao_Tome', + 'Atlantic/Reykjavik', + 'Atlantic/Faroe', + 'Africa/Banjul', + 'Atlantic/St_Helena', + 'Africa/Bissau', + 'Atlantic/Canary', + 'Etc/UTC' + ] + ], + [ + '338947200', + [ + 'Africa/Abidjan', + 'Africa/Dakar', + 'Africa/Accra', + 'Africa/Bamako', + 'Africa/Conakry', + 'Africa/Ouagadougou', + 'Africa/Monrovia', + 'Africa/Lome', + 'Africa/Nouakchott', + 'Africa/Freetown', + 'Africa/Sao_Tome', + 'Atlantic/Reykjavik', + 'Atlantic/Faroe', + 'Africa/Banjul', + 'Atlantic/St_Helena', + 'Africa/Bissau', + 'Etc/UTC' + ] + ], + [ + '347155200', + [ + 'Africa/Abidjan', + 'Africa/Dakar', + 'Africa/Accra', + 'Africa/Bamako', + 'Africa/Conakry', + 'Africa/Ouagadougou', + 'Africa/Monrovia', + 'Africa/Lome', + 'Africa/Nouakchott', + 'Africa/Freetown', + 'Africa/Sao_Tome', + 'Atlantic/Reykjavik', + 'Africa/Banjul', + 'Atlantic/St_Helena', + 'Africa/Bissau', + 'Etc/UTC' + ] + ], + [ + '820465200', + [ + 'Africa/Abidjan', + 'Africa/Dakar', + 'Africa/Accra', + 'Africa/Bamako', + 'Africa/Conakry', + 'Africa/Ouagadougou', + 'Africa/Monrovia', + 'Africa/Lome', + 'Africa/Nouakchott', + 'Africa/Freetown', + 'Africa/Sao_Tome', + 'Atlantic/Reykjavik', + 'Africa/Banjul', + 'Atlantic/St_Helena', + 'Africa/Bissau', + 'America/Danmarkshavn', + 'Etc/UTC' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'Africa/Casablanca', + 'Africa/Algiers', + 'Atlantic/Madeira', + 'Africa/Ceuta' + ] + ], + [ + '57722400', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Africa/Algiers', + 'Europe/Dublin', + 'Atlantic/Madeira', + 'Africa/Ceuta' + ] + ], + [ + '198291600', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Africa/Algiers', + 'Europe/Dublin', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Africa/Ceuta' + ] + ], + [ + '212544000', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Africa/Algiers', + 'Europe/Dublin', + 'Europe/Lisbon', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Africa/Ceuta' + ] + ], + [ + '246240000', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Europe/Dublin', + 'Europe/Lisbon', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Africa/Ceuta' + ] + ], + [ + '309740400', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Africa/Algiers', + 'Europe/Dublin', + 'Europe/Lisbon', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Africa/Ceuta' + ] + ], + [ + '338947200', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Africa/Algiers', + 'Europe/Dublin', + 'Europe/Lisbon', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Africa/Ceuta', + 'Atlantic/Canary' + ] + ], + [ + '347155200', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Africa/Algiers', + 'Europe/Dublin', + 'Europe/Lisbon', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Africa/Ceuta', + 'Atlantic/Faroe', + 'Atlantic/Canary' + ] + ], + [ + '357523200', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Europe/Dublin', + 'Europe/Lisbon', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Africa/Ceuta', + 'Atlantic/Faroe', + 'Atlantic/Canary' + ] + ], + [ + '448243200', + [ + 'Europe/London', + 'Europe/Dublin', + 'Europe/Lisbon', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Atlantic/Faroe', + 'Atlantic/Canary' + ] + ], + [ + '504918000', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Europe/Dublin', + 'Europe/Lisbon', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Atlantic/Faroe', + 'Atlantic/Canary' + ] + ], + [ + '717555600', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Europe/Dublin', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Atlantic/Faroe', + 'Atlantic/Canary' + ] + ], + [ + '717559200', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Europe/Dublin', + 'Atlantic/Azores', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Atlantic/Faroe', + 'Atlantic/Canary' + ] + ], + [ + '733280400', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Europe/Dublin', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Atlantic/Faroe', + 'Atlantic/Canary' + ] + ], + [ + '828234000', + [ + 'Europe/London', + 'Africa/Casablanca', + 'Europe/Dublin', + 'Europe/Lisbon', + 'Atlantic/Madeira', + 'Africa/El_Aaiun', + 'Atlantic/Faroe', + 'Atlantic/Canary' + ] + ] + ] + }, + '-0500' => { + 'N' => [ + [ + '0', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Detroit', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Menominee', + 'America/Atikokan', + 'Etc/GMT-5' + ] + ], + [ + '31554000', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Detroit', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Menominee', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'Etc/GMT-5' + ] + ], + [ + '94712400', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Thunder_Bay', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Menominee', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Vevay', + 'Etc/GMT-5' + ] + ], + [ + '104914800', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Thunder_Bay', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Vevay', + 'Etc/GMT-5' + ] + ], + [ + '105084000', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Managua', + 'America/Indiana/Indianapolis', + 'America/Thunder_Bay', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Vevay', + 'Etc/GMT-5' + ] + ], + [ + '126248400', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Managua', + 'America/Indiana/Indianapolis', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Vevay', + 'Etc/GMT-5' + ] + ], + [ + '136364400', + [ + 'America/Panama', + 'America/Guayaquil', + 'America/Managua', + 'America/Indiana/Indianapolis', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Vevay', + 'Etc/GMT-5' + ] + ], + [ + '157784400', + [ + 'America/Panama', + 'America/Guayaquil', + 'America/Managua', + 'America/Indiana/Indianapolis', + 'America/Detroit', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Vevay', + 'Etc/GMT-5' + ] + ], + [ + '161758800', + [ + 'America/Panama', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Detroit', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Vevay', + 'Etc/GMT-5' + ] + ], + [ + '167814000', + [ + 'America/Panama', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Vevay', + 'Etc/GMT-5' + ] + ], + [ + '189320400', + [ + 'America/Panama', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '247046400', + [ + 'America/Panama', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '377935200', + [ + 'America/Panama', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Merida', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '407653200', + [ + 'America/Panama', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '441781200', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Cayman', + 'Pacific/Galapagos', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '504939600', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Cayman', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '590043600', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '688550400', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '694260000', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Managua', + 'America/Indiana/Indianapolis', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '717310800', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '725868000', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Managua', + 'America/Indiana/Indianapolis', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '749192400', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Managua', + 'America/Indiana/Indianapolis', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '780210000', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Managua', + 'America/Indiana/Indianapolis', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '852094800', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '972806400', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Rankin_Inlet', + 'America/Indiana/Vevay', + 'America/Cambridge_Bay', + 'America/Indiana/Marengo', + 'America/Resolute', + 'Etc/GMT-5' + ] + ], + [ + '973400400', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Rankin_Inlet', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'America/Resolute', + 'Etc/GMT-5' + ] + ], + [ + '986112000', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Indiana/Indianapolis', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Indiana/Marengo', + 'Etc/GMT-5' + ] + ], + [ + '1136091600', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Indiana/Tell_City', + 'America/Atikokan', + 'America/Indiana/Knox', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'Etc/GMT-5' + ] + ], + [ + '1143961200', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Atikokan', + 'Etc/GMT-5' + ] + ], + [ + '1162108800', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Atikokan', + 'America/Resolute', + 'Etc/GMT-5' + ] + ], + [ + '1173600000', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Atikokan', + 'Etc/GMT-5' + ] + ], + [ + '1214283600', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Cayman', + 'America/Atikokan', + 'Etc/GMT-5' + ] + ], + [ + '1384056000', + [ + 'America/Panama', + 'America/Jamaica', + 'America/Guayaquil', + 'America/Rio_Branco', + 'America/Cayman', + 'America/Eirunepe', + 'America/Atikokan', + 'Etc/GMT-5' + ] + ] + ], + 'Y' => [ + [ + '0', + [ + 'America/New_York', + 'America/Santo_Domingo', + 'America/Port-au-Prince', + 'America/Indiana/Indianapolis', + 'America/Kentucky/Louisville', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Indiana/Vincennes', + 'America/Bogota', + 'America/Indiana/Tell_City', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Indiana/Winamac', + 'America/Indiana/Vevay', + 'America/Nipigon', + 'America/Nassau', + 'America/Indiana/Marengo', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '31554000', + [ + 'America/New_York', + 'America/Santo_Domingo', + 'America/Port-au-Prince', + 'America/Kentucky/Louisville', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Indiana/Vevay', + 'America/Nipigon', + 'America/Nassau', + 'America/Indiana/Marengo', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '94712400', + [ + 'America/New_York', + 'America/Santo_Domingo', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Rio_Branco', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Indiana/Marengo', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '126248400', + [ + 'America/New_York', + 'America/Santo_Domingo', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Indiana/Marengo', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '126687600', + [ + 'America/New_York', + 'America/Santo_Domingo', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '136364400', + [ + 'America/New_York', + 'America/Jamaica', + 'America/Santo_Domingo', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '152082000', + [ + 'America/New_York', + 'America/Jamaica', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '152092800', + [ + 'America/New_York', + 'America/Jamaica', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Indiana/Marengo', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '157784400', + [ + 'America/New_York', + 'America/Jamaica', + 'America/Port-au-Prince', + 'America/Kentucky/Louisville', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Indiana/Marengo', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '167814000', + [ + 'America/New_York', + 'America/Jamaica', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Indiana/Marengo', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '189320400', + [ + 'America/New_York', + 'America/Jamaica', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '377935200', + [ + 'America/New_York', + 'America/Jamaica', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Cancun', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '441781200', + [ + 'America/New_York', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Cancun', + 'America/Rio_Branco', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '590043600', + [ + 'America/New_York', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Cancun', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '749192400', + [ + 'America/New_York', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Cancun', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Eirunepe', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '780210000', + [ + 'America/New_York', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Cancun', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '796802400', + [ + 'America/New_York', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Cancun', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Pangnirtung', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '902041200', + [ + 'America/New_York', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Bogota', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Pangnirtung', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '941353200', + [ + 'America/New_York', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Bogota', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '972799200', + [ + 'America/New_York', + 'America/Santo_Domingo', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Bogota', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '972806400', + [ + 'America/New_York', + 'America/Santo_Domingo', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Bogota', + 'America/Kentucky/Monticello', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Pangnirtung', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '975823200', + [ + 'America/New_York', + 'America/Port-au-Prince', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Bogota', + 'America/Kentucky/Monticello', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Nipigon', + 'America/Pangnirtung', + 'America/Nassau', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '1136091600', + [ + 'America/New_York', + 'America/Port-au-Prince', + 'America/Indiana/Indianapolis', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Bogota', + 'America/Kentucky/Monticello', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Indiana/Vevay', + 'America/Nipigon', + 'America/Pangnirtung', + 'America/Nassau', + 'America/Indiana/Marengo', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '1173600000', + [ + 'America/New_York', + 'America/Port-au-Prince', + 'America/Indiana/Indianapolis', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Bogota', + 'America/Kentucky/Monticello', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Indiana/Winamac', + 'America/Indiana/Vevay', + 'America/Nipigon', + 'America/Pangnirtung', + 'America/Nassau', + 'America/Indiana/Marengo', + 'America/Montreal', + 'America/Grand_Turk' + ] + ], + [ + '1194163200', + [ + 'America/New_York', + 'America/Port-au-Prince', + 'America/Indiana/Indianapolis', + 'America/Detroit', + 'America/Kentucky/Louisville', + 'America/Thunder_Bay', + 'America/Lima', + 'America/Indiana/Vincennes', + 'America/Bogota', + 'America/Kentucky/Monticello', + 'America/Iqaluit', + 'America/Toronto', + 'America/Havana', + 'America/Indiana/Winamac', + 'America/Indiana/Petersburg', + 'America/Indiana/Vevay', + 'America/Nipigon', + 'America/Pangnirtung', + 'America/Nassau', + 'America/Indiana/Marengo', + 'America/Montreal', + 'America/Grand_Turk' + ] + ] + ] + }, + '+0630' => { + 'N' => [ + [ + '0', + [ + 'Asia/Rangoon', + 'Indian/Cocos' + ] + ], + [ + '832962600', + [ + 'Asia/Rangoon', + 'Asia/Colombo', + 'Indian/Cocos' + ] + ], + [ + '846266400', + [ + 'Asia/Rangoon', + 'Indian/Cocos' + ] + ] + ] + } +} +; + +# +# This list is copied from: +# AjaxApp/API/Mailbox.pm +# http://wiki.zimbra.com/wiki/Time_Zones_in_ZCS +# + +our %OtherLinks = ( + 'AUS Central Standard Time' => 'Australia/Darwin', + 'AUS Central' => 'Australia/Darwin', + 'AUS Eastern Standard Time' => 'Australia/Sydney', + 'AUS Eastern' => 'Australia/Sydney', + 'Afghanistan Standard Time' => 'Asia/Kabul', + 'Afghanistan' => 'Asia/Kabul', + 'Alaskan Standard Time' => 'America/Anchorage', + 'Alaskan' => 'America/Anchorage', + 'Arab Standard Time' => 'Asia/Riyadh', + 'Arab' => 'Asia/Riyadh', + 'Arabian Standard Time' => 'Asia/Muscat', + 'Arabian' => 'Asia/Muscat', + 'Arabic Standard Time' => 'Asia/Baghdad', + 'Argentina Standard Time' => 'America/Argentina/Buenos_Aires', + 'Armenian Standard Time' => 'Asia/Yerevan', + 'Atlantic Standard Time' => 'America/Halifax', + 'Atlantic' => 'America/Halifax', + 'Azerbaijan Standard Time' => 'Asia/Baku', + 'Azores Standard Time' => 'Atlantic/Azores', + 'Azores' => 'Atlantic/Azores', + 'Bangkok Standard Time' => 'Asia/Bangkok', + 'Bangkok' => 'Asia/Bangkok', + 'Bangladesh Standard Time' => 'Asia/Dhaka', + 'Beijing' => 'Asia/Shanghai', + 'Canada Central Standard Time' => 'America/Regina', + 'Canada Central' => 'America/Regina', + 'Cape Verde Standard Time' => 'Atlantic/Cape_Verde', + 'Caucasus Standard Time' => 'Asia/Yerevan', + 'Caucasus' => 'Asia/Yerevan', + 'Cen. Australia Standard Time' => 'Australia/Adelaide', + 'Cen. Australia' => 'Australia/Adelaide', + 'Central America Standard Time' => 'America/Regina', + 'Central Asia Standard Time' => 'Asia/Almaty', + 'Central Asia' => 'Asia/Almaty', + 'Central Brazilian Standard Time' => 'America/Cuiaba', + 'Central Europe Standard Time' => 'Europe/Prague', + 'Central Europe' => 'Europe/Prague', + 'Central European Standard Time' => 'Europe/Belgrade', + 'Central European' => 'Europe/Belgrade', + 'Central Pacific Standard Time' => 'Pacific/Guadalcanal', + 'Central Pacific' => 'Pacific/Guadalcanal', + 'Central Standard Time (Mexico)' => 'America/Mexico_City', + 'Central Standard Time' => 'America/Chicago', + 'Central' => 'America/Chicago', + 'China Standard Time' => 'Asia/Shanghai', + 'China' => 'Asia/Shanghai', + 'E. Africa Standard Time' => 'Africa/Nairobi', + 'E. Africa' => 'Africa/Nairobi', + 'E. Australia Standard Time' => 'Australia/Brisbane', + 'E. Australia' => 'Australia/Brisbane', + 'E. Europe Standard Time' => 'Europe/Minsk', + 'E. Europe' => 'Europe/Minsk', + 'E. South America Standard Time' => 'America/Sao_Paulo', + 'E. South America' => 'America/Sao_Paulo', + 'Eastern Standard Time' => 'America/New_York', + 'Eastern' => 'America/New_York', + 'Egypt Standard Time' => 'Africa/Cairo', + 'Egypt' => 'Africa/Cairo', + 'Ekaterinburg Standard Time' => 'Asia/Yekaterinburg', + 'Ekaterinburg' => 'Asia/Yekaterinburg', + 'FLE Standard Time' => 'Europe/Helsinki', + 'FLE' => 'Europe/Helsinki', + 'Fiji Standard Time' => 'Pacific/Fiji', + 'Fiji' => 'Pacific/Fiji', + 'GFT Standard Time' => 'Europe/Athens', + 'GFT' => 'Europe/Athens', + 'GMT Standard Time' => 'Europe/London', + 'GMT' => 'Europe/London', + 'GTB Standard Time' => 'Europe/Athens', + 'GTB' => 'Europe/Athens', + 'Georgian Standard Time' => 'Asia/Tbilisi', + 'Greenland Standard Time' => 'America/Godthab', + 'Hawaiian Standard Time' => 'Pacific/Honolulu', + 'Hawaiian' => 'Pacific/Honolulu', + 'India Standard Time' => 'Asia/Calcutta', + 'India' => 'Asia/Calcutta', + 'Iran Standard Time' => 'Asia/Tehran', + 'Iran' => 'Asia/Tehran', + 'Israel Standard Time' => 'Asia/Jerusalem', + 'Israel' => 'Asia/Jerusalem', + 'Jordan Standard Time' => 'Asia/Amman', + 'Kamchatka Standard Time' => 'Asia/Kamchatka', + 'Korea Standard Time' => 'Asia/Seoul', + 'Korea' => 'Asia/Seoul', + 'Magadan Standard Time' => 'Asia/Magadan', + 'Mauritius Standard Time' => 'Indian/Mauritius', + 'Mexico Standard Time 2' => 'America/Chihuahua', + 'Mexico Standard Time' => 'America/Mexico_City', + 'Mexico' => 'America/Mexico_City', + 'Mid-Atlantic Standard Time' => 'Atlantic/South_Georgia', + 'Mid-Atlantic' => 'Atlantic/South_Georgia', + 'Middle East Standard Time' => 'Asia/Beirut', + 'Montevideo Standard Time' => 'America/Montevideo', + 'Morocco Standard Time' => 'Africa/Casablanca', + 'Mountain Standard Time (Mexico)' => 'America/Chihuahua', + 'Mountain Standard Time' => 'America/Denver', + 'Mountain' => 'America/Denver', + 'Myanmar Standard Time' => 'Asia/Rangoon', + 'N. Central Asia Standard Time' => 'Asia/Novosibirsk', + 'Namibia Standard Time' => 'Africa/Windhoek', + 'Nepal Standard Time' => 'Asia/Katmandu', + 'New Zealand Standard Time' => 'Pacific/Auckland', + 'New Zealand' => 'Pacific/Auckland', + 'Newfoundland Standard Time' => 'America/St_Johns', + 'Newfoundland' => 'America/St_Johns', + 'North Asia East Standard Time' => 'Asia/Irkutsk', + 'North Asia Standard Time' => 'Asia/Krasnoyarsk', + 'Pacific SA Standard Time' => 'America/Santiago', + 'Pacific SA' => 'America/Santiago', + 'Pacific Standard Time (Mexico)' => 'America/Tijuana', + 'Pacific Standard Time' => 'America/Los_Angeles', + 'Pacific' => 'America/Los_Angeles', + 'Pakistan Standard Time' => 'Asia/Karachi', + 'Paraguay Standard Time' => 'America/Asuncion', + 'Prague Bratislava' => 'Europe/Prague', + 'Romance Standard Time' => 'Europe/Paris', + 'Romance' => 'Europe/Paris', + 'Russian Standard Time' => 'Europe/Moscow', + 'Russian' => 'Europe/Moscow', + 'SA Eastern Standard Time' => 'America/Cayenne', + 'SA Eastern' => 'America/Cayenne', + 'SA Pacific Standard Time' => 'America/Bogota', + 'SA Pacific' => 'America/Bogota', + 'SA Western Standard Time' => 'America/Guyana', + 'SA Western' => 'America/Guyana', + 'SE Asia Standard Time' => 'Asia/Bangkok', + 'SE Asia' => 'Asia/Bangkok', + 'Samoa Standard Time' => 'Pacific/Apia', + 'Samoa' => 'Pacific/Apia', + 'Saudi Arabia Standard Time' => 'Asia/Riyadh', + 'Saudi Arabia' => 'Asia/Riyadh', + 'Singapore Standard Time' => 'Asia/Singapore', + 'Singapore' => 'Asia/Singapore', + 'South Africa Standard Time' => 'Africa/Harare', + 'South Africa' => 'Africa/Harare', + 'Sri Lanka Standard Time' => 'Asia/Colombo', + 'Sri Lanka' => 'Asia/Colombo', + 'Sydney Standard Time' => 'Australia/Sydney', + 'Syria Standard Time' => 'Asia/Damascus', + 'Taipei Standard Time' => 'Asia/Taipei', + 'Taipei' => 'Asia/Taipei', + 'Tasmania Standard Time' => 'Australia/Hobart', + 'Tasmania' => 'Australia/Hobart', + 'Tokyo Standard Time' => 'Asia/Tokyo', + 'Tokyo' => 'Asia/Tokyo', + 'Tonga Standard Time' => 'Pacific/Tongatapu', + 'US Eastern Standard Time' => 'America/Indianapolis', + 'US Eastern' => 'America/Indianapolis', + 'US Mountain Standard Time' => 'America/Phoenix', + 'US Mountain' => 'America/Phoenix', + 'US-Alaskan' => 'America/Anchorage', + 'US-Arizona' => 'America/Phoenix', + 'US-Central' => 'America/Chicago', + 'US-Eastern' => 'America/New_York', + 'US-Mountain' => 'America/Denver', + 'US-Pacific' => 'America/Los_Angeles', + 'US/Alaskan' => 'America/Anchorage', + 'US/Arizona' => 'America/Phoenix', + 'US/Central' => 'America/Chicago', + 'US/Eastern' => 'America/New_York', + 'US/Mountain' => 'America/Denver', + 'US/Pacific' => 'America/Los_Angeles', + 'Ulaanbaatar Standard Time' => 'Asia/Ulaanbaatar', + 'Venezuela Standard Time' => 'America/Caracas', + 'Vladivostok Standard Time' => 'Asia/Vladivostok', + 'Vladivostok' => 'Asia/Vladivostok', + 'W. Australia Standard Time' => 'Australia/Perth', + 'W. Australia' => 'Australia/Perth', + 'W. Central Africa Standard Time' => 'Africa/Luanda', + 'W. Europe Standard Time' => 'Europe/Berlin', + 'W. Europe' => 'Europe/Berlin', + 'Warsaw' => 'Europe/Warsaw', + 'West Asia Standard Time' => 'Asia/Karachi', + 'West Asia' => 'Asia/Karachi', + 'West Pacific Standard Time' => 'Pacific/Guam', + 'West Pacific' => 'Pacific/Guam', + 'Western Brazilian Standard Time' => 'America/Rio_Branco', + 'Yakutsk Standard Time' => 'Asia/Yakutsk', + 'Yakutsk' => 'Asia/Yakutsk', + '(GMT-12.00) International Date Line West' => 'Etc/GMT-12', + '(GMT-11.00) Midway Island / Samoa' => 'Pacific/Midway', + '(GMT-10.00) Hawaii' => 'Pacific/Honolulu', + '(GMT-09.00) Alaska' => 'America/Anchorage', + '(GMT-08.00) Pacific Time (US & Canada)' => 'America/Los_Angeles', + '(GMT-08.00) Tijuana / Baja California' => 'America/Tijuana', + '(GMT-07.00) Arizona' => 'America/Phoenix', + '(GMT-07.00) Chihuahua / La Paz / Mazatlan - New' => 'America/Chihuahua', + '(GMT-07.00) Chihuahua / La Paz / Mazatlan - Old' => 'America/Chihuahua', + '(GMT-07.00) Mountain Time (US & Canada)' => 'America/Denver', + '(GMT-06.00) Central America' => 'America/Chicago', + '(GMT-06.00) Central Time (US & Canada)' => 'America/Chicago', + '(GMT-06.00) Guadalajara / Mexico City / Monterrey - New' => 'America/Mexico_City', + '(GMT-06.00) Guadalajara / Mexico City / Monterrey - Old' => 'America/Mexico_City', + '(GMT-06.00) Saskatchewan' => 'America/Belize', + '(GMT-05.00) Bogota / Lima / Quito / Rio Branco' => 'America/Bogota', + '(GMT-05.00) Eastern Time (US & Canada)' => 'America/New_York', + '(GMT-05.00) Indiana (East)' => 'America/Indiana/Indianapolis', + '(GMT-04.00) Atlantic Time (Canada)' => 'America/Glace_Bay', + '(GMT-04.00) Caracas / La Paz' => 'America/Caracas', + '(GMT-04.00) Manaus' => 'America/Manaus', + '(GMT-04.00) Santiago' => 'America/Santiago', + '(GMT-03.30) Newfoundland' => 'America/St_Johns', + '(GMT-03.00) Brasilia' => 'America/Sao_Paulo', + '(GMT-03.00) Buenos Aires / Georgetown' => 'America/Argentina/Buenos_Aires', + '(GMT-03.00) Greenland' => 'America/Godthab', + '(GMT-03.00) Montevideo' => 'America/Montevideo', + '(GMT-02.00) Mid-Atlantic' => 'America/Noronha', + '(GMT-01.00) Azores' => 'Atlantic/Azores', + '(GMT-01.00) Cape Verde Is.' => 'Atlantic/Cape_Verde', + '(GMT) Casablanca / Monrovia / Reykjavik' => 'Africa/Casablanca', + '(GMT) Greenwich Mean Time - Dublin / Edinburgh / Lisbon / London' => 'Etc/UTC', + '(GMT+01.00) Amsterdam / Berlin / Bern / Rome / Stockholm / Vienna' => 'Europe/Amsterdam', + '(GMT+01.00) Belgrade / Bratislava / Budapest / Ljubljana / Prague' => 'Europe/Belgrade', + '(GMT+01.00) Brussels / Copenhagen / Madrid / Paris' => 'Europe/Brussels', + '(GMT+01.00) Sarajevo / Skopje / Warsaw / Zagreb' => 'Europe/Warsaw', + '(GMT+01.00) West Central Africa' => 'Africa/Algiers', + '(GMT+02.00) Amman' => 'Asia/Amman', + '(GMT+02.00) Athens / Bucharest / Istanbul' => 'Europe/Athens', + '(GMT+02.00) Beirut' => 'Asia/Beirut', + '(GMT+02.00) Cairo' => 'Africa/Cairo', + '(GMT+02.00) Harare / Pretoria' => 'Africa/Harare', + '(GMT+02.00) Helsinki / Kyiv / Riga / Sofia / Tallinn / Vilnius' => 'Europe/Helsinki', + '(GMT+02.00) Jerusalem' => 'Asia/Jerusalem', + '(GMT+02.00) Minsk' => 'Europe/Minsk', + '(GMT+02.00) Windhoek' => 'Africa/Windhoek', + '(GMT+03.00) Baghdad' => 'Asia/Baghdad', + '(GMT+03.00) Kuwait / Riyadh' => 'Asia/Kuwait', + '(GMT+03.00) Moscow / St. Petersburg / Volgograd' => 'Europe/Moscow', + '(GMT+03.00) Nairobi' => 'Africa/Nairobi', + '(GMT+03.00) Tbilisi' => 'Asia/Tbilisi', + '(GMT+03.30) Tehran' => 'Asia/Tehran', + '(GMT+04.00) Abu Dhabi / Muscat' => 'Asia/Dubai', + '(GMT+04.00) Baku' => 'Asia/Baku', + '(GMT+04.00) Yerevan' => 'Asia/Yerevan', + '(GMT+04.30) Kabul' => 'Asia/Kabul', + '(GMT+05.00) Ekaterinburg' => 'Asia/Yekaterinburg', + '(GMT+05.00) Islamabad / Karachi / Tashkent' => 'Asia/Karachi', + '(GMT+05.30) Chennai / Kolkata / Mumbai / New Delhi' => 'Asia/Kolkata', + '(GMT+05.30) Sri Jayawardenepura' => 'Asia/Colombo', + '(GMT+05.45) Kathmandu' => 'Asia/Kathmandu', + '(GMT+06.00) Almaty / Novosibirsk' => 'Asia/Almaty', + '(GMT+06.00) Astana / Dhaka' => 'Asia/Dhaka', + '(GMT+06.30) Yangon (Rangoon)' => 'Asia/Rangoon', + '(GMT+07.00) Bangkok / Hanoi / Jakarta' => 'Asia/Bangkok', + '(GMT+07.00) Krasnoyarsk' => 'Asia/Krasnoyarsk', + '(GMT+08.00) Beijing / Chongqing / Hong Kong / Urumqi' => 'Asia/Shanghai', + '(GMT+08.00) Irkutsk / Ulaan Bataar' => 'Asia/Irkutsk', + '(GMT+08.00) Kuala Lumpur / Singapore' => 'Asia/Kuala_Lumpur', + '(GMT+08.00) Perth' => 'Australia/Perth', + '(GMT+08.00) Taipei' => 'Asia/Taipei', + '(GMT+09.00) Osaka / Sapporo / Tokyo' => 'Asia/Tokyo', + '(GMT+09.00) Seoul' => 'Asia/Seoul', + '(GMT+09.00) Yakutsk' => 'Asia/Yakutsk', + '(GMT+09.30) Adelaide' => 'Australia/Adelaide', + '(GMT+09.30) Darwin' => 'Australia/Darwin', + '(GMT+10.00) Brisbane' => 'Australia/Brisbane', + '(GMT+10.00) Canberra / Melbourne / Sydney' => 'Australia/Sydney', + '(GMT+10.00) Guam / Port Moresby' => 'Pacific/Guam', + '(GMT+10.00) Hobart' => 'Australia/Hobart', + '(GMT+10.00) Vladivostok' => 'Asia/Vladivostok', + '(GMT+11.00) Magadan / Solomon Is. / New Caledonia' => 'Asia/Magadan', + '(GMT+12.00) Auckland / Wellington' => 'Pacific/Auckland', + '(GMT+12.00) Fiji / Kamchatka / Marshall Is.' => 'Pacific/Fiji', + "(GMT+13.00) Nuku'alofa" => 'Pacific/Tongatapu', +); + +our %OtherLinksReversed; + +foreach my $OtherLink (keys %OtherLinks) { + push @{$OtherLinksReversed{$OtherLinks{$OtherLink}}}, $OtherLink; +} + +=head1 SUBROUTINES/METHODS + +=head2 $Class->GetTimeZone(%Args) + +Args: + + TZID - zone name + StandardTzOffsetTo - offset + +Pick the matching timezone with the highest population size to the offset +if the zone name isn't known. + +Returns a DateTime::TimeZone object + +=cut + +sub GetTimeZone { + my ($Class, %Args) = @_; + + # can we short circuit {{{ + + if ($Args{TZID}) { + my $Name = $OtherLinks{$Args{TZID}} + ? $OtherLinks{$Args{TZID}} + : $Args{TZID}; + + my $TimeZone = eval {DateTime::TimeZone->new(name => $Name)}; + + if ($TimeZone and $TimeZone->is_olson()) { + return $TimeZone->name(); + } + } + + return '' unless exists $Args{StandardTzOffsetTo}; + + # }}} + + # get set of timezones for provided standard offset {{{ + + my $Now = DateTime->now()->strftime("%Y%m%dT%H%M%S"); + my $Time = DateTime::Format::ISO8601->parse_datetime(($Args{Time} || $Now))->epoch(); + my $HasDST = $Args{DaylightTzOffsetTo} ? 'Y' : 'N'; + + return '' unless exists $ZonesByOffset->{$Args{StandardTzOffsetTo}}{$HasDST}; + + my @TimeZones; + + foreach my $Range (reverse @{$ZonesByOffset->{$Args{StandardTzOffsetTo}}{$HasDST}}) { + if ($Range->[0] <= $Time) { + @TimeZones = @{$Range->[1]}; + last; + } + } + + return '' unless @TimeZones; + + # }}} + + if ($Args{TZID} and ($Args{TZID} =~ /\w/)) { + # try to match provided TZID with Olson timezones {{{ + + my %TimeZoneEndings; + + foreach my $TimeZone (@TimeZones) { + my (@TimeZoneParts) = split /[^a-z0-9\+\-\_]+/i, $TimeZone; + $TimeZoneEndings{$TimeZoneParts[-1]} = $TimeZone; + } + + my (@TZIDParts) = reverse split /[^a-z0-9\+\-\_]+/i, $Args{TZID}; + + my %Distances; + + foreach my $TZIDPart (@TZIDParts) { + foreach my $TimeZoneEnding (keys %TimeZoneEndings) { + my $Distance = distance(lc($TZIDPart), lc($TimeZoneEnding)); + + if ($Distance == 0) { + return $TimeZoneEndings{$TimeZoneEnding}; + } + + my $MaxLength = (length($TZIDPart) > length($TimeZoneEnding)) + ? length($TZIDPart) + : length($TimeZoneEnding); + + if ($Distance < int($MaxLength/2)) { + $Distances{$Distance}{$TimeZoneEndings{$TimeZoneEnding}} = 1; + } + } + } + + # }}} + + # try to match provided TZID with links {{{ + + foreach my $TimeZone (@TimeZones) { + next unless @{$OtherLinksReversed{$TimeZone} || []}; + + foreach my $OtherLink (@{$OtherLinksReversed{$TimeZone}}) { + my $Distance = distance(lc($Args{TZID}), lc($OtherLink)); + + if ($Distance == 0) { + return $TimeZone; + } + + my $MaxLength = (length($Args{TZID}) > length($OtherLink)) + ? length($Args{TZID}) + : length($OtherLink); + + if ($Distance < int($MaxLength/2)) { + $Distances{$Distance}{$TimeZone} = 1; + } + } + } + + # }}} + + if (%Distances) { + my ($Shortest) = sort { $a <=> $b } keys %Distances; + + # @TimeZones is sorted by population size, so in a tie, biggest population wins + foreach my $TimeZone (@TimeZones) { + return $TimeZone if $Distances{$Shortest}{$TimeZone}; + } + } + } + + # damn, let's fallback {{{ + + my ($Etc) = grep { m{^Etc/} } @TimeZones; + return $Etc if $Etc; + + # @TimeZones is sorted by population size + return $TimeZones[0]; + + # }}} +} + +=head2 $Class->GetVTimeZone($TimeZone) + +Returns a Data::ICal::TimeZone object for the named zone + +=cut + +sub GetVTimeZone { + my ($Class, $TimeZone) = @_; + + return '' unless $TimeZone; + return '' unless $RulesByZone->{$TimeZone}; + + my $TZ = Data::ICal::TimeZone->new( timezone => $TimeZone ); + + return $TZ->definition(); +} + +=head1 LICENSE AND COPYRIGHT + +Copyright 2015 Bron Gondwana. + +This program is free software; you can redistribute it and/or modify it +under the terms of the the Artistic License (2.0). You may obtain a +copy of the full license at: + +L + +Any use, modification, and distribution of the Standard or Modified +Versions is governed by this Artistic License. By using, modifying or +distributing the Package, you accept this license. Do not use, modify, +or distribute the Package, if you do not accept this license. + +If your Modified Version has been derived from a Modified Version made +by someone other than you, you are nevertheless required to ensure that +your Modified Version complies with the requirements of this license. + +This license does not grant you the right to use any trademark, service +mark, tradename, or logo of the Copyright Holder. + +This license includes the non-exclusive, worldwide, free-of-charge +patent license to make, have made, use, offer to sell, sell, import and +otherwise transfer the Package with respect to any patent claims +licensable by the Copyright Holder that are necessarily infringed by the +Package. If you institute patent litigation (including a cross-claim or +counterclaim) against any party alleging that the Package constitutes +direct or contributory patent infringement, then this Artistic License +to you shall terminate on the date that such litigation is filed. + +Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER +AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. +THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY +YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR +CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR +CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +=cut + +1; # End of Net::CalDAVTalk::TimeZone diff --git a/t/00-load.t b/t/00-load.t new file mode 100644 index 0000000..ad0b3ea --- /dev/null +++ b/t/00-load.t @@ -0,0 +1,13 @@ +#!perl -T +use 5.006; +use strict; +use warnings FATAL => 'all'; +use Test::More; + +plan tests => 1; + +BEGIN { + use_ok( 'Net::CalDAVTalk' ) || print "Bail out!\n"; +} + +diag( "Testing Net::CalDAVTalk $Net::CalDAVTalk::VERSION, Perl $], $^X" ); diff --git a/t/manifest.t b/t/manifest.t new file mode 100644 index 0000000..6ddfe36 --- /dev/null +++ b/t/manifest.t @@ -0,0 +1,15 @@ +#!perl -T +use 5.006; +use strict; +use warnings FATAL => 'all'; +use Test::More; + +unless ( $ENV{RELEASE_TESTING} ) { + plan( skip_all => "Author tests not required for installation" ); +} + +my $min_tcm = 0.9; +eval "use Test::CheckManifest $min_tcm"; +plan skip_all => "Test::CheckManifest $min_tcm required" if $@; + +ok_manifest(); diff --git a/t/pod-coverage.t b/t/pod-coverage.t new file mode 100644 index 0000000..866fac2 --- /dev/null +++ b/t/pod-coverage.t @@ -0,0 +1,20 @@ +#!perl -T +use 5.006; +use strict; +use warnings FATAL => 'all'; +use Test::More; + +# Ensure a recent version of Test::Pod::Coverage +my $min_tpc = 1.08; +eval "use Test::Pod::Coverage $min_tpc"; +plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage" + if $@; + +# Test::Pod::Coverage doesn't require a minimum Pod::Coverage version, +# but older versions don't recognize some common documentation styles +my $min_pc = 0.18; +eval "use Pod::Coverage $min_pc"; +plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage" + if $@; + +all_pod_coverage_ok(); diff --git a/t/pod.t b/t/pod.t new file mode 100644 index 0000000..a0054e9 --- /dev/null +++ b/t/pod.t @@ -0,0 +1,12 @@ +#!perl -T +use 5.006; +use strict; +use warnings FATAL => 'all'; +use Test::More; + +# Ensure a recent version of Test::Pod +my $min_tp = 1.22; +eval "use Test::Pod $min_tp"; +plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; + +all_pod_files_ok();