Merge remote-tracking branch 'jacktang/gmt-offset-fix'
Conflicts: src/localtime.erl
This commit is contained in:
commit
32cb7d9e90
4 changed files with 72 additions and 38 deletions
|
@ -1,9 +1,10 @@
|
||||||
TZDIR=tzdata
|
TZDIR=tzdata
|
||||||
TZ_FILES=$(addprefix $(TZDIR)/, africa antarctica asia australasia backward etcetera europe northamerica southamerica)
|
TZ_FILES=$(addprefix $(TZDIR)/, africa antarctica asia australasia backward etcetera europe northamerica southamerica)
|
||||||
|
|
||||||
|
tzout: DATE := $(shell date +%F)
|
||||||
tzout: $(TZ_FILES)
|
tzout: $(TZ_FILES)
|
||||||
TZ_VERSION=`perl -n -e 'm/^VERSION\s*=\s*(\S+)/ and print $$1;' $(TZDIR)/Makefile`; \
|
TZ_VERSION=`perl -n -e 'm/^VERSION\s*=\s*(\S+)/ and print $$1;' $(TZDIR)/Makefile`; \
|
||||||
./tz-erl --version $$TZ_VERSION -o $@ $^
|
./tz-erl --version $$TZ_VERSION --date $(DATE) -o $@ $^
|
||||||
|
|
||||||
$(TZ_FILES): $(TZDIR)
|
$(TZ_FILES): $(TZDIR)
|
||||||
|
|
||||||
|
|
42
db/tz-erl
42
db/tz-erl
|
@ -145,15 +145,17 @@ sub process_data {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Converts an offset in the format "[+-]?HH:MM" or "[+-]?HH" into minutes.
|
||||||
|
# For example, "2:00" -> 120, "-0:30" -> -30, "+5" -> 300.
|
||||||
sub offset_minutes {
|
sub offset_minutes {
|
||||||
my ($off, $adj) = @_;
|
my ($off, $adj) = @_;
|
||||||
|
|
||||||
my $convert_offset = sub {
|
my $convert_offset = sub {
|
||||||
my $m = $_[0];
|
$_[0] =~ m/^([\+\-]?)(\d+)(?::(\d+))?$/
|
||||||
if ($m =~ m/^([\+\-]?)(?:(\d+):)?(\d+)$/) {
|
or die "offset \"$_[0]\" did not match";
|
||||||
$m = (defined $2 ? $2 : 0) * MPH + $3;
|
my $m = $2 * MPH;
|
||||||
|
if (defined $3) { $m += $3; }
|
||||||
if ($1 eq '-') { $m = -$m; }
|
if ($1 eq '-') { $m = -$m; }
|
||||||
}
|
|
||||||
return $m;
|
return $m;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -256,9 +258,13 @@ sub zone_line {
|
||||||
# We ignore any zone line that has a definite until (end) time that
|
# We ignore any zone line that has a definite until (end) time that
|
||||||
# is in the past.
|
# is in the past.
|
||||||
if (defined $until) {
|
if (defined $until) {
|
||||||
my $until_year = ($until =~ m/^(\d+)/)[0];
|
my ($until_year, $until_month, $until_day) = split_ymd($until);
|
||||||
if ($until_year >= $current_year) {
|
if (($until_year > $current_year) ||
|
||||||
die "until $until not handled";
|
(($until_year == $current_year) &&
|
||||||
|
(($until_month > $current_month) ||
|
||||||
|
(($until_month == $current_month) &&
|
||||||
|
($until_day >= $current_day))))) {
|
||||||
|
"future until \"$until\" not handled";
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -286,7 +292,10 @@ sub zone_line {
|
||||||
$rule1 = $rule2 = RULE_NULL;
|
$rule1 = $rule2 = RULE_NULL;
|
||||||
} elsif (scalar(@rules) == 1) {
|
} elsif (scalar(@rules) == 1) {
|
||||||
# One active rule. This is a year that DST started or stopped
|
# One active rule. This is a year that DST started or stopped
|
||||||
# being observed
|
# being observed. erlang_localtime doesn't handle this. If DST
|
||||||
|
# stopped being observed in this year, don't output a DST rule.
|
||||||
|
# If DST started being observed, do. (Except that we don't handle
|
||||||
|
# this yet.)
|
||||||
print STDERR Data::Dump::dump(\@rules), "\n";
|
print STDERR Data::Dump::dump(\@rules), "\n";
|
||||||
die "one rule for $name";
|
die "one rule for $name";
|
||||||
$name1 = zonename($format, $rules[0]->[RULE_LETTERS], undef);
|
$name1 = zonename($format, $rules[0]->[RULE_LETTERS], undef);
|
||||||
|
@ -427,6 +436,23 @@ INIT {
|
||||||
%dow_from_name= map { $dow_to_name[$_] => $_ } (0..$#dow_to_name);
|
%dow_from_name= map { $dow_to_name[$_] => $_ } (0..$#dow_to_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub split_ymd {
|
||||||
|
my ($ymd) = @_;
|
||||||
|
$ymd =~ m/^(\d+)(?:\s+(\w+)(?:\s+(\d+)))?/
|
||||||
|
or die "parse \"$ymd\" for ymd failed";
|
||||||
|
my $year = $1;
|
||||||
|
my $month = do {
|
||||||
|
if (defined $2) {
|
||||||
|
defined $mon_from_name{$2} or die "parse \"$ymd\" for month failed";
|
||||||
|
$mon_from_name{$2};
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
my $day = defined $3 ? $3 : 0;
|
||||||
|
return ($year, $month, $day);
|
||||||
|
}
|
||||||
|
|
||||||
sub on_to_day_of_month {
|
sub on_to_day_of_month {
|
||||||
my ($on, $year, $month) = @_;
|
my ($on, $year, $month) = @_;
|
||||||
|
|
||||||
|
|
|
@ -427,33 +427,33 @@
|
||||||
{"Eire",{"GMT","GMT"},{"IST","IST"},0,60,{last,sun,mar},{1,0},{last,sun,oct},{2,0}},
|
{"Eire",{"GMT","GMT"},{"IST","IST"},0,60,{last,sun,mar},{1,0},{last,sun,oct},{2,0}},
|
||||||
{"Etc/GMT",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+0",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+0",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+1",{"GMT+1","GMT+1"},undef,-1,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+1",{"GMT+1","GMT+1"},undef,60,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+10",{"GMT+10","GMT+10"},undef,-10,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+10",{"GMT+10","GMT+10"},undef,600,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+11",{"GMT+11","GMT+11"},undef,-11,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+11",{"GMT+11","GMT+11"},undef,660,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+12",{"GMT+12","GMT+12"},undef,-12,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+12",{"GMT+12","GMT+12"},undef,720,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+2",{"GMT+2","GMT+2"},undef,-2,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+2",{"GMT+2","GMT+2"},undef,120,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+3",{"GMT+3","GMT+3"},undef,-3,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+3",{"GMT+3","GMT+3"},undef,180,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+4",{"GMT+4","GMT+4"},undef,-4,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+4",{"GMT+4","GMT+4"},undef,240,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+5",{"GMT+5","GMT+5"},undef,-5,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+5",{"GMT+5","GMT+5"},undef,300,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+6",{"GMT+6","GMT+6"},undef,-6,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+6",{"GMT+6","GMT+6"},undef,360,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+7",{"GMT+7","GMT+7"},undef,-7,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+7",{"GMT+7","GMT+7"},undef,420,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+8",{"GMT+8","GMT+8"},undef,-8,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+8",{"GMT+8","GMT+8"},undef,480,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT+9",{"GMT+9","GMT+9"},undef,-9,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT+9",{"GMT+9","GMT+9"},undef,540,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-0",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-0",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-1",{"GMT-1","GMT-1"},undef,1,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-1",{"GMT-1","GMT-1"},undef,-60,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-10",{"GMT-10","GMT-10"},undef,10,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-10",{"GMT-10","GMT-10"},undef,-600,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-11",{"GMT-11","GMT-11"},undef,11,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-11",{"GMT-11","GMT-11"},undef,-660,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-12",{"GMT-12","GMT-12"},undef,12,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-12",{"GMT-12","GMT-12"},undef,-720,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-13",{"GMT-13","GMT-13"},undef,13,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-13",{"GMT-13","GMT-13"},undef,-780,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-14",{"GMT-14","GMT-14"},undef,14,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-14",{"GMT-14","GMT-14"},undef,-840,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-2",{"GMT-2","GMT-2"},undef,2,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-2",{"GMT-2","GMT-2"},undef,-120,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-3",{"GMT-3","GMT-3"},undef,3,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-3",{"GMT-3","GMT-3"},undef,-180,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-4",{"GMT-4","GMT-4"},undef,4,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-4",{"GMT-4","GMT-4"},undef,-240,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-5",{"GMT-5","GMT-5"},undef,5,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-5",{"GMT-5","GMT-5"},undef,-300,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-6",{"GMT-6","GMT-6"},undef,6,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-6",{"GMT-6","GMT-6"},undef,-360,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-7",{"GMT-7","GMT-7"},undef,7,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-7",{"GMT-7","GMT-7"},undef,-420,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-8",{"GMT-8","GMT-8"},undef,8,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-8",{"GMT-8","GMT-8"},undef,-480,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT-9",{"GMT-9","GMT-9"},undef,9,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT-9",{"GMT-9","GMT-9"},undef,-540,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/GMT0",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
{"Etc/GMT0",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/Greenwich",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
{"Etc/Greenwich",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
||||||
{"Etc/UCT",{"UCT","UCT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
{"Etc/UCT",{"UCT","UCT"},undef,0,0,undef,{0,0},undef,{0,0}},
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
,get_timezone/1
|
,get_timezone/1
|
||||||
,list_timezones/0
|
,list_timezones/0
|
||||||
,adjust_datetime/2
|
,adjust_datetime/2
|
||||||
|
,fmt_shift/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
% utc_to_local(UtcDateTime, Timezone) -> LocalDateTime | [LocalDateTime, DstLocalDateTime] | {error, ErrDescr}
|
% utc_to_local(UtcDateTime, Timezone) -> LocalDateTime | [LocalDateTime, DstLocalDateTime] | {error, ErrDescr}
|
||||||
|
@ -214,6 +215,8 @@ fmt_shift({'+', H, M}) ->
|
||||||
H * 60 + M;
|
H * 60 + M;
|
||||||
fmt_shift({'-', H, M}) ->
|
fmt_shift({'-', H, M}) ->
|
||||||
-(H * 60 + M);
|
-(H * 60 + M);
|
||||||
|
fmt_shift(0) ->
|
||||||
|
0;
|
||||||
fmt_shift(Any) ->
|
fmt_shift(Any) ->
|
||||||
throw(Any).
|
throw(Any).
|
||||||
|
|
||||||
|
@ -231,14 +234,18 @@ tr_char([H|T], From, To, Acc) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-define(SPACE_CHAR, 32).
|
-define(SPACE_CHAR, 32).
|
||||||
get_timezone_inner(TimeZone) ->
|
get_timezone_inner(TimeZone) when is_binary(TimeZone) ->
|
||||||
|
get_timezone_inner(erlang:binary_to_list(TimeZone));
|
||||||
|
get_timezone_inner(TimeZone) when is_list(TimeZone) ->
|
||||||
TimeZoneNoSpaces = tr_char(TimeZone, ?SPACE_CHAR, $_),
|
TimeZoneNoSpaces = tr_char(TimeZone, ?SPACE_CHAR, $_),
|
||||||
case dict:find(TimeZoneNoSpaces, ?tz_index) of
|
case dict:find(TimeZoneNoSpaces, ?tz_index) of
|
||||||
error ->
|
error ->
|
||||||
TimeZoneNoSpaces;
|
TimeZoneNoSpaces;
|
||||||
{ok, [TZName | _]} ->
|
{ok, [TZName | _]} ->
|
||||||
TZName
|
TZName
|
||||||
end.
|
end;
|
||||||
|
get_timezone_inner(_) ->
|
||||||
|
throw({error, "Timezone should be string/binary"}).
|
||||||
|
|
||||||
-ifdef(TEST).
|
-ifdef(TEST).
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue