diff --git a/.github/workflows/tests-workflow.yml b/.github/workflows/tests-workflow.yml deleted file mode 100644 index 70a9145..0000000 --- a/.github/workflows/tests-workflow.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: qdate tests and dialyzer -on: push - -jobs: - linux: - name: OTP ${{ matrix.otp_version }} - runs-on: ${{ matrix.os }} - continue-on-error: true - - strategy: - matrix: - include: - - os: ubuntu-22.04 - otp_version: '27.x' - rebar3_version: "3.24.0" - - os: ubuntu-22.04 - otp_version: '27.x' - rebar3_version: "3.23.0" - - os: ubuntu-22.04 - otp_version: '26.x' - rebar3_version: "3.22.1" - - os: ubuntu-22.04 - otp_version: '25.x' - rebar3_version: "3.22.1" - - os: ubuntu-22.04 - otp_version: '24.x' - rebar3_version: "3.22.1" - - os: ubuntu-20.04 - otp_version: '23.x' - rebar3_version: "3.19.0" - - steps: - - name: Install OTP ${{matrix.otp_version}} - uses: erlef/setup-beam@v1 - with: - version-type: loose - otp-version: ${{ matrix.otp_version}} - rebar3-version: ${{ matrix.rebar3_version}} - - - name: Checkout qdate - uses: actions/checkout@v4 - - - name: Run Tests - run: make test - - - name: Run Dialyzer - run: make dialyzer diff --git a/.gitignore b/.gitignore index 6ff84d8..253f03c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,3 @@ ebin/ .eunit/ .idea/ _build -doc/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5de773f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: erlang +script: "make test" +otp_release: + - 23.0 + - 22.3 + - 21.3 + - 20.3 +before_script: "sudo apt-get --yes --force-yes install libpam-runtime python-software-properties software-properties-common" diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown index f44c11c..18f9a5f 100644 --- a/CHANGELOG.markdown +++ b/CHANGELOG.markdown @@ -1,18 +1,3 @@ -## 0.7.3 - -* Remove the `?else` macro. - -## 0.7.2 - -* Update the error message when qdate is not started with some better instructions. -* Some minor updates for hex.pm -* Removed the `erlnow()` warning -* Fix some typos in the documentation -* Update the makefile to use [rebar3.mk](https://rebar3.mk) -* Skipped 0.7.1 only because there was a partially tagged 0.7.1 for a while, - but was never published to hex. Just to ensure upgrades are easier, I just skipped - a proper 0.7.1 release - ## 0.7.0 * Re-introduce the qdate server for storing qdate timezones, formats, and parsers, @@ -37,7 +22,7 @@ just the opposite of `beginning_X`) * Add `between/[2,3,5]` functions for computing whether a date/time is between two others. -* Update to rebar3 and add hex compatibility. (@Licenser) +* Update to rebar3 and add hex compatability. (@Licenser) * Properly add dependent apps to .app.src (@Licenser) * Add an optional "relative date/time parser". * Fix: Ensure `get_timezone()` returns the default timezone (from config) if it diff --git a/LICENSE.md b/LICENSE similarity index 100% rename from LICENSE.md rename to LICENSE diff --git a/Makefile b/Makefile index de4d762..08d6350 100644 --- a/Makefile +++ b/Makefile @@ -1,41 +1,33 @@ -all: compile +REBAR_PATH = $(shell which rebar3) -# Check if rebar3.mk exists, and if not, download it -ifeq ("$(wildcard rebar3.mk)","") -$(shell curl -O https://raw.githubusercontent.com/choptastic/rebar3.mk/master/rebar3.mk) +ifeq ($(REBAR_PATH),) +REBAR = $(shell pwd)/rebar3 +else +REBAR = rebar3 endif -# rebar3.mk adds a new rebar3 rule to your Makefile -# (see https://github.com/choptastic/rebar3.mk) for full info -include rebar3.mk -compile: rebar3 +all: compile + +compile: $(REBAR) compile -update: rebar3 +update: $(REBAR) update -test: - EUNIT=1 $(REBAR) compile - EUNIT=1 $(REBAR) eunit +test: compile + $(REBAR) eunit dialyzer: compile - DIALYZER=1 $(REBAR) dialyzer + $(REBAR) dialyzer -dev: - mkdir -p _checkouts - cd _checkouts; git clone https://github.com/choptastic/qdate_localtime +travis: test dialyzer - -run: rebar3 +run: $(REBAR) shell -push_tags: - git push --tag - -pull_tags: - git pull --tag - -publish: rebar3 pull_tags - $(REBAR) hex publish +publish: + $(REBAR) as pkg upgrade + $(REBAR) as pkg hex publish + $(REBAR) upgrade diff --git a/README.md b/README.markdown similarity index 98% rename from README.md rename to README.markdown index a462a9b..d12f64d 100644 --- a/README.md +++ b/README.markdown @@ -1,6 +1,6 @@ # qdate - Erlang Date and Timezone Library -[![qdate tests and dialyzer](https://github.com/choptastic/qdate/actions/workflows/tests-workflow.yml/badge.svg)](https://github.com/choptastic/qdate/actions/workflows/tests-workflow.yml) +[![Build Status](https://travis-ci.org/choptastic/qdate.png?branch=master)](https://travis-ci.org/choptastic/qdate) ## Purpose @@ -107,7 +107,7 @@ will infer the timezone in the following order. #### Disambiguating Ambiguous Timezone Conversions -Sometimes, when you're converting a datetime from one timezone to another, there +Sometimes, when youre converting a datetime from one timezone to another, there are potentially two different results if the conversion happens to land on in a timezone that's in the middle of a Daylight Saving conversion. For example, converting "11-Nov-2013 1:00:am" in "America/New York" to "GMT" could be both @@ -536,7 +536,7 @@ qdate:between(qdate:add_minutes(-15), Date, qdate:add_minutes(15)). %% But, you don't have to: if that's a common format you use in your %% application, you can register your format with the `qdate` server, and then -%% easily refer to that format by its key. +%% easiy refer to that format by its key. %% So let's take that format and register it 16> qdate:register_format(longdate, "l, F jS, Y g:i A T"). @@ -720,7 +720,7 @@ the week" calculation. This has three forms, specifically: 7=Sunday). + `beginning_week(DayOfWeek, Date)` - Calculates the beginning of the week based on the provided `DayOfWeek`. Valid values for DayOfWeek are the - integers 1-7 or the atom versions of the days of the week. Specifically: + integers 1-7 or the atom verions of the days of the week. Specifically: * Monday: `1 | monday | mon` * Tuesday: `2 | tuesday | tue` diff --git a/rebar.config b/rebar.config index 9dc3672..de7ef3f 100644 --- a/rebar.config +++ b/rebar.config @@ -10,15 +10,5 @@ {deps, [ erlware_commons, - {qdate_localtime, "~> 1.2.0"} + {qdate_localtime, "1.2.0"} ]}. - -{project_plugins, [rebar3_ex_doc]}. - -{hex, [{doc, ex_doc}]}. - -{ex_doc, [ - {source_url, <<"https://github.com/choptastic/qdate">>}, - {extras, [<<"README.md">>, <<"LICENSE.md">>]}, - {main, <<"readme">>}]}. - diff --git a/rebar.config.script b/rebar.config.script index 61542d6..e57d8e3 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -9,7 +9,7 @@ case erlang:function_exported(rebar3, main, 1) of %% Rebuild deps, possibly including those that have been moved to %% profiles [{deps, [ - {erlware_commons, "", {git, "https://github.com/erlware/erlware_commons", {tag, "v1.5.0"}}}, %% this is the version of erlware_commons that works until erlware tags a new version - {qdate_localtime, "", {git, "https://github.com/choptastic/qdate_localtime", {tag, "1.1.0"}}} + {erlware_commons, "", {git, "git://github.com/erlware/erlware_commons", {tag, "v1.5.0"}}}, %% this is the version of erlware_commons that works until erlware tags a new version + {qdate_localtime, "", {git, "git://github.com/choptastic/qdate_localtime", {tag, "1.1.0"}}} ]} | lists:keydelete(deps, 1, CONFIG)] end. diff --git a/rebar.lock b/rebar.lock index 30b2fae..7b02d75 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,14 +1,14 @@ {"1.2.0", [{<<"cf">>,{pkg,<<"cf">>,<<"0.3.1">>},1}, - {<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"1.6.0">>},0}, - {<<"qdate_localtime">>,{pkg,<<"qdate_localtime">>,<<"1.2.1">>},0}]}. + {<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"1.5.0">>},0}, + {<<"qdate_localtime">>,{pkg,<<"qdate_localtime">>,<<"1.1.0">>},0}]}. [ {pkg_hash,[ {<<"cf">>, <<"5CB902239476E141EA70A740340233782D363A31EEA8AD37049561542E6CD641">>}, - {<<"erlware_commons">>, <<"E0DA62F91E65DEFAE28BB450DDC3C24E85ECB99B926F857CDC6ED8E7DD7076B4">>}, - {<<"qdate_localtime">>, <<"72E1034DC6B7FEE8F588281EDDD0BD0DC5260005D758052F50634D265D382C18">>}]}, + {<<"erlware_commons">>, <<"918C56D8FB3BE52AF0DF138ED6E0755E764AD4467CD7D025761F7D0A17D3DEC1">>}, + {<<"qdate_localtime">>, <<"5F6C3ACF10ECC5A7E2EFA3DCD2C863102B962188DBD9E086EC01D29FE029DA29">>}]}, {pkg_hash_ext,[ {<<"cf">>, <<"315E8D447D3A4B02BCDBFA397AD03BBB988A6E0AA6F44D3ADD0F4E3C3BF97672">>}, - {<<"erlware_commons">>, <<"B57C299C39A2992A8C413F9D2C1B8A20061310FB4432B0EEE5E4C4DF7AAA0AA3">>}, - {<<"qdate_localtime">>, <<"1109958D205C65C595C8C5694CB83EBAF2DBE770CF902E4DCE8AFB2C4123764D">>}]} + {<<"erlware_commons">>, <<"3E7C6FB2BA4C29B0DD5DFE9D031B66449E2088ECEC1A81465BD9FDE05ED7D0DB">>}, + {<<"qdate_localtime">>, <<"91928E066DA6BCC745FF18B7C368347457CAF9250AD00950E9DA18E129D49EC5">>}]} ]. diff --git a/rebar3 b/rebar3 new file mode 100755 index 0000000..6f0ccfa Binary files /dev/null and b/rebar3 differ diff --git a/src/qdate.app.src b/src/qdate.app.src index 2479739..7b85ef4 100644 --- a/src/qdate.app.src +++ b/src/qdate.app.src @@ -1,16 +1,17 @@ {application, qdate, [ {description, "Simple Date and Timezone handling for Erlang"}, - {vsn, git}, + {vsn, "0.7.0"}, {registered, []}, {applications, [ kernel, - stdlib, qdate_localtime, - erlware_commons + erlware_commons, + stdlib ]}, {modules, [qdate, qdate_srv, qdate_sup, qdate_app]}, {env, []}, + {maintainers, ["Jesse Gumm"]}, {licenses, ["MIT"]}, {mod, {qdate_app, []}}, {links, [{"Github", "https://github.com/choptastic/qdate"}]} diff --git a/src/qdate.erl b/src/qdate.erl index 7027b27..f11c00a 100644 --- a/src/qdate.erl +++ b/src/qdate.erl @@ -1,5 +1,5 @@ % vim: ts=4 sw=4 et -% Copyright (c) 2013-2023 Jesse Gumm +% Copyright (c) 2013-2019 Jesse Gumm % See LICENSE for licensing information. % -module(qdate). @@ -145,7 +145,6 @@ {{integer(), integer(), integer()}, {integer(), integer(), integer(), integer()}}. -type erlnow() :: {integer(), integer(), integer()}. -type binary_or_string() :: binary() | string(). --type disambiguate() :: prefer_standard | prefer_daylight | both. %% erlang:get_stacktrace/0 is deprecated in OTP 21 -ifndef(OTP_RELEASE). @@ -162,6 +161,7 @@ -define(DETERMINE_TZ, determine_timezone()). -define(DEFAULT_DISAMBIG, prefer_standard). +-define(else, true). start() -> @@ -179,7 +179,7 @@ to_string(Format, Date) -> to_string(Format, ToTZ, Date) -> to_string(Format, ToTZ, ?DEFAULT_DISAMBIG, Date). --spec to_string(Format :: any(), ToTZ :: any(), Disambiguate :: disambiguate(), Date :: qdate()) -> binary_or_string() | {ambiguous, binary_or_string() , binary_or_string()}. +-spec to_string(Format :: any(), ToTZ :: any(), Disambiguate :: atom(), Date :: qdate()) -> binary_or_string() | {ambiguous, binary_or_string() , binary_or_string()}. to_string(FormatKey, ToTZ, Disambiguate, Date) when is_atom(FormatKey) orelse is_tuple(FormatKey) -> Format = case qdate_srv:get_format(FormatKey) of undefined -> throw({undefined_format_key,FormatKey}); @@ -303,7 +303,7 @@ to_date(RawDate) -> to_date(ToTZ, RawDate) -> to_date(ToTZ, ?DEFAULT_DISAMBIG, RawDate). --spec to_date(ToTZ :: any(), Disambiguate :: disambiguate(), RawDate :: any()) -> {ambiguous, datetime(), datetime()} | datetime(). +-spec to_date(ToTZ :: any(), Disambiguate :: atom(), RawDate :: any()) -> {ambiguous, datetime(), datetime()} | datetime(). to_date(ToTZ, Disambiguate, RawDate) when is_binary(RawDate) -> to_date(ToTZ, Disambiguate, binary_to_list(RawDate)); to_date(ToTZ, Disambiguate, RawDate) when is_binary(ToTZ) -> @@ -361,7 +361,7 @@ get_deterministic_datetime() -> to_unixtime(Date) -> to_unixtime(?DEFAULT_DISAMBIG, Date). --spec to_unixtime(Disamb :: disambiguate(), qdate()) -> {ambiguous, integer(), integer()} | integer(). +-spec to_unixtime(Disamb :: atom(), qdate()) -> integer() | {ambiguous, integer(), integer()}. to_unixtime(_, Unixtime) when is_integer(Unixtime) -> Unixtime; to_unixtime(_, {MegaSecs,Secs,_}) when is_integer(MegaSecs), is_integer(Secs) -> @@ -383,12 +383,12 @@ unixtime() -> to_now(Date) -> to_now(?DEFAULT_DISAMBIG, Date). --spec to_now(Disamb :: disambiguate(), qdate()) -> erlnow() | {ambiguous, erlnow(), erlnow()}. +-spec to_now(Disamb :: atom(), qdate()) -> {integer(), integer(), integer()} | {ambiguous, tuple(), tuple()}. to_now(_, Now = {_,_,_}) -> Now; to_now(Disamb, ToParse) -> case to_unixtime(Disamb, ToParse) of - {ambiguous, Standard, Daylight} when is_integer(Standard), is_integer(Daylight) -> + {ambiguous, Standard, Daylight} -> {ambiguous, unixtime_to_now(Standard), unixtime_to_now(Daylight)}; @@ -1064,8 +1064,6 @@ determine_timezone() -> %% If FromTZ is an integer, then it's an integer that represents the number of minutes %% relative to GMT. So we convert the date to GMT based on that number, then we can %% do the other timezone conversion. --spec date_tz_to_tz(Date :: datetime(), Disambiguate :: disambiguate(), FromTZ :: any(), ToTZ :: any()) -> - datetime() | {ambiguous, datetime(), datetime()}. date_tz_to_tz(Date, Disambiguate, FromTZ, ToTZ) when is_integer(FromTZ) -> NewDate = localtime:adjust_datetime(Date, FromTZ), date_tz_to_tz(NewDate, Disambiguate, "GMT", ToTZ); @@ -1087,7 +1085,7 @@ date_tz_to_tz_both(Date, FromTZ, ToTZ) -> if Standard=:=Daylight -> Standard; - true -> + ?else -> {ambiguous, Standard, Daylight} end. @@ -1206,8 +1204,6 @@ flooring(N) when N < 0 -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% TESTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --ifdef(EUNIT). - -include_lib("eunit/include/eunit.hrl"). %% emulates as if a forum-type website has a Site tz, and a user-specified tz @@ -1531,5 +1527,3 @@ microsoft_parser(_) -> stop_test(_) -> ok. - --endif. diff --git a/src/qdate_srv.erl b/src/qdate_srv.erl index 731b8b1..d09b782 100644 --- a/src/qdate_srv.erl +++ b/src/qdate_srv.erl @@ -152,26 +152,8 @@ unset_env(Key) -> gen_server:call(?SERVER, {unset, ?KEY(Key)}). get_all_env(FilterTag) -> - try ets:tab2list(?TABLE) of - All -> - [{Key, V} || {{?BASETAG, {Tag, Key}}, V} <- All, Tag==FilterTag] - catch - error:badarg:S -> - Msg = maybe_start_msg(), - logger:error(Msg), - - error({qdate_get_all_env_failed, #{ - original_error => {error, badarg, S} - }}) - end. - -maybe_start_msg() -> - "Attempting to read qdate environment failed (qdate_srv:get_all_env/1).\n" - "qdate may not have been started properly.\n" - "Please ensure qdate is started properly by either:\n" - "* Putting qdate in the 'applications' key in your .app.src or .app file, or\n" - "* Starting it manually with application:ensure_all_started(qdate) or qdate:start().". - + All = ets:tab2list(?TABLE), + [{Key, V} || {{?BASETAG, {Tag, Key}}, V} <- All, Tag==FilterTag]. %% ProcDic Vars