diff --git a/.gitignore b/.gitignore index b4bcb39..1fcd342 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ _build/ *~ src/tz_index.erl *.sw? +rebar3 diff --git a/Makefile b/Makefile index 7ddd15e..152df64 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,26 @@ -all: +all: rebar3 ./rebar3 compile -check: +check: rebar3 ./rebar3 eunit -dialyzer: +test: check + +dialyzer: rebar3 ./rebar3 dialyzer -publish: +publish: rebar3 ./rebar3 hex publish + +rebar3: + @(echo "Building rebar3...") + @(rm -fr tmp) + @(mkdir -p tmp) + @(cd tmp && \ + git clone https://github.com/erlang/rebar3 && \ + cd rebar3 && \ + ./bootstrap) + @(echo "Moving rebar3 executable locally (NOT installing system-wide)") + @(mv tmp/rebar3/rebar3 .) + @(echo "Cleaning up rebar3 remnants") + @(rm -fr tmp) diff --git a/README.md b/README.md index 19144ca..6e69541 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,21 @@ ## NOTE -This is a fork of -[erlang_localtime](https://github.com/dmitryme/erlang_localtime), modified -specifically for compatibility with +This is a fork of the excellent library, +[erlang_localtime](https://github.com/dmitryme/erlang_localtime). The purpose +of this fork is specifically for compatibility with [qdate](https://github.com/choptastic/qdate). The two are mostly compatible, -but have diverged a bit over the years. The qdate tests will not pass if the -original erlang_localtime dependency is used due to some subtle differences to -attempt to make qdate a little bit smarter. +but have diverged slightly over the years. The qdate tests will not pass if the +original `erlang_localtime dependency` is used due to some subtle differences +to attempt to make qdate a little bit smarter. #### Public exports -* utc_to_local(DateTime, Timezone) - converts UTC time to local according to specified Timezone -* local_to_utc(DateTime, Timezone) - converts local time to UTC -* local_to_local(DateTime, TimezoneFrom, TimezoneTo) - converts local time to local -* tz_name(DateTime, Timezone) - returns a timezone name (E.g. MSK, MSD, etc) -* tz_shift(DateTime, Timezone) - returns time difference between local datetime and GMT -* tz_shift(DateTime, TimezoneFrom, TimezoneTo) - returns time difference between local datetime and required timezone +* `utc_to_local(DateTime, Timezone)` - converts UTC time to local according to specified Timezone +* `local_to_utc(DateTime, Timezone)` - converts local time to UTC +* `local_to_local(DateTime, TimezoneFrom, TimezoneTo)` - converts local time to local +* `tz_name(DateTime, Timezone)` - returns a timezone name (E.g. MSK, MSD, etc) +* `tz_shift(DateTime, Timezone)` - returns time difference between local datetime and GMT +* `tz_shift(DateTime, TimezoneFrom, TimezoneTo)` - returns time difference between local datetime and required timezone Where DateTime = {date(), time()} TimeZone(To, From) = String(). E.g. “Europe/Moscow”, “America/NewYork”. Or abbreviations "MSK", "MSD", etc. Note: diff --git a/include/tz_database.hrl b/include/tz_database.hrl index 4cfd583..bbde520 100644 --- a/include/tz_database.hrl +++ b/include/tz_database.hrl @@ -35,7 +35,7 @@ %% Discarded excess rules for Zone Africa/El_Aaiun. %% Moving rule to beginning of day for Zone America/Godthab. %% Moving rule to beginning of day for Zone America/Godthab. - %% Rounded timezone rules of Asia/Tehran to week 3 in march and september + %% Removed DST from Iran and Asia/Tehran {"Africa/Abidjan",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}}, {"Africa/Accra",{"GMT","GMT"},undef,0,0,undef,{0,0},undef,{0,0}}, @@ -347,7 +347,7 @@ {"Asia/Taipei",{"CST","CST"},undef,480,0,undef,{0,0},undef,{0,0}}, {"Asia/Tashkent",{"UZT","UZT"},undef,300,0,undef,{0,0},undef,{0,0}}, {"Asia/Tbilisi",{"GET","GET"},undef,240,0,undef,{0,0},undef,{0,0}}, - {"Asia/Tehran",{"IRST","IRST"},{"IRDT","IRDT"},210,60,{3,sat,mar},{0,0},{3,sat,sep},{0,0}}, + {"Asia/Tehran",{"IRST","IRST"},undef,210,0,undef,{0,0},undef,{0,0}}, {"Asia/Tel_Aviv",{"IST","IST"},{"IDT","IDT"},120,60,{4,fri,mar},{2,0},{last,sun,oct},{2,0}}, {"Asia/Thimbu",{"BTT","BTT"},undef,360,0,undef,{0,0},undef,{0,0}}, {"Asia/Thimphu",{"BTT","BTT"},undef,360,0,undef,{0,0},undef,{0,0}}, @@ -535,7 +535,7 @@ {"Indian/Mauritius",{"MUT","MUT"},undef,240,0,undef,{0,0},undef,{0,0}}, {"Indian/Mayotte",{"EAT","EAT"},undef,180,0,undef,{0,0},undef,{0,0}}, {"Indian/Reunion",{"RET","RET"},undef,240,0,undef,{0,0},undef,{0,0}}, - {"Iran",{"IRST","IRST"},{"IRDT","IRDT"},210,60,undef,{0,0},undef,{0,0}}, + {"Iran",{"IRST","IRST"},undef,210,0,undef,{0,0},undef,{0,0}}, {"Israel",{"IST","IST"},{"IDT","IDT"},120,60,{4,fri,mar},{2,0},{last,sun,oct},{2,0}}, {"Jamaica",{"EST","EST"},undef,-300,0,undef,{0,0},undef,{0,0}}, {"Japan",{"JST","JST"},undef,540,0,undef,{0,0},undef,{0,0}}, diff --git a/priv/db/.gitignore b/priv/db/.gitignore new file mode 100644 index 0000000..badaa65 --- /dev/null +++ b/priv/db/.gitignore @@ -0,0 +1,3 @@ +tzout +tzdata/ +*.tar.gz diff --git a/db/Makefile b/priv/db/Makefile similarity index 82% rename from db/Makefile rename to priv/db/Makefile index 44071f0..dc2cb42 100644 --- a/db/Makefile +++ b/priv/db/Makefile @@ -3,7 +3,7 @@ TZ_FILES=$(addprefix $(TZDIR)/, africa antarctica asia australasia backward etce tzout: DATE := $(shell date +%F) tzout: $(TZ_FILES) - TZ_VERSION=`perl -n -e 'm/^VERSION\s*=\s*(\S+)/ and print $$1;' $(TZDIR)/Makefile`; \ + TZ_VERSION=`cat $(TZDIR)/version`; \ ./tz-erl --version $$TZ_VERSION --date $(DATE) -o $@ $^ $(TZ_FILES): $(TZDIR) @@ -14,4 +14,5 @@ $(TZDIR): tzdata-latest.tar.gz tzdata-latest.tar.gz: curl -O "ftp://ftp.iana.org/tz/tzdata-latest.tar.gz" - +clean: + @(rm -fr tzdata *.tar.gz tzout *~) diff --git a/db/tz-erl b/priv/db/tz-erl similarity index 95% rename from db/tz-erl rename to priv/db/tz-erl index 3f41e21..bcc743e 100755 --- a/db/tz-erl +++ b/priv/db/tz-erl @@ -459,11 +459,16 @@ sub on_to_day_of_month { my $day; if ($on =~ m/^\d+$/) { $day = $on; + print "Day extracted via regex to: $day\n"; } else { my ($desired_dow, $time_base); if ($on =~ m/^(\w+)>=(\d+)$/) { $desired_dow = $dow_from_name{$1}; my $desired_day = $2; $time_base = timelocal(0, 0, 0, $desired_day, $month, $year); + print "Regex: $on => desired_dow: $desired_dow. Time_base: $time_base\n"; + } elsif ($on =~ m/^(\w+)<=(\d+)$/) { + $desired_dow = $dow_from_name{$1}; my $desired_day = $2; + $time_base = timelocal(0, 0, 0, $desired_day, $month, $year); } elsif ($on =~ m/^last(\w+)$/) { $desired_dow = $dow_from_name{$1}; # One week before the beginning of the next month. @@ -472,7 +477,12 @@ sub on_to_day_of_month { die "match $on failed"; } ($day, my $dow) = (localtime($time_base))[3,6]; - if ($dow != $desired_dow) { $day += (DPW + $desired_dow - $dow) % DPW; } + print "Current Day: $day\n"; + print "Comparing $dow = $desired_dow\n"; + if ($dow != $desired_dow) { + $day += (DPW + $desired_dow - $dow) % DPW; + } + print "After comparison: Current Day: $day\n"; } return $day; @@ -511,6 +521,10 @@ sub last_active_epoch { } my $day = on_to_day_of_month($on, $year, $month); + print "On=$on, Year=$year, Month=$month ====> Day=$day\n"; + ## changing the below call to timelocal_nocheck stops the crash, but it feels wrong + ## especially since without it, it seems to produce a lot of "redundant" error messages + ## I don't have time to explore this now, but I'll come back to it return timelocal(0, 0, 0, $day, $month, $year); } diff --git a/rebar.config b/rebar.config index 1aad9de..781bcf2 100644 --- a/rebar.config +++ b/rebar.config @@ -6,6 +6,6 @@ {pre_hooks,[ {"linux|bsd|darwin|solaris", compile, "priv/ibuild.escript"}, - {"win32", compile, "escript.exe priv\\ibuild.escript"} + {"win32", compile, "escript.exe priv/ibuild.escript"} ]}. diff --git a/rebar.lock b/rebar.lock deleted file mode 100644 index 57afcca..0000000 --- a/rebar.lock +++ /dev/null @@ -1 +0,0 @@ -[]. diff --git a/rebar3 b/rebar3 deleted file mode 100755 index 6f0ccfa..0000000 Binary files a/rebar3 and /dev/null differ diff --git a/src/localtime.erl b/src/localtime.erl index 1cbcf94..0bf952a 100644 --- a/src/localtime.erl +++ b/src/localtime.erl @@ -255,10 +255,12 @@ tr_char_test() -> ?assertEqual("A_C_E", tr_char("A C E", ?SPACE_CHAR, $_)). tz_name_test() -> - ?assertEqual({"CET", "CET"}, tz_name({{2008,12,10},{15,30,0}}, "Europe/Amsterdam")), - ?assertEqual({"IRST", "IRST"}, tz_name({{2008,12,10},{15,30,0}}, "Asia/Tehran")), - ?assertEqual({"IRDT", "IRDT"}, tz_name({{2020,5,4},{15,30,0}}, "Asia/Tehran")). - + ?assertEqual({"CET", "CET"}, tz_name({{2008,12,10},{15,30,0}}, "Europe/Amsterdam")), + %%% No DST in Iran + ?assertEqual({"IRST", "IRST"}, tz_name({{2008,12,10},{15,30,0}}, "Asia/Tehran")), + ?assertEqual({"IRST", "IRST"}, tz_name({{2020,5,4},{15,30,0}}, "Asia/Tehran")), + ?assertEqual({"IRST", "IRST"}, tz_name({{2008,12,10},{15,30,0}}, "Iran")), + ?assertEqual({"IRST", "IRST"}, tz_name({{2020,5,4},{15,30,0}}, "Iran")). get_timezone_test() -> ?assertEqual("America/Los_Angeles", get_timezone("America/Los Angeles")). diff --git a/src/qdate_localtime.app.src b/src/qdate_localtime.app.src index 1f5e01f..a7d9093 100644 --- a/src/qdate_localtime.app.src +++ b/src/qdate_localtime.app.src @@ -1,7 +1,7 @@ {application, 'qdate_localtime', [ {description, "Erlang library for conversion from one local time to another (forked specifically for qdate compatibility)"}, - {vsn, "1.2.0"}, + {vsn, "1.2.1"}, {applications, [kernel, stdlib]}, {modules, []}, {registered, []},