Added function parse_to_local_datetime/1

To utilize parse/1 but to give you {date(), time()} in the local timezone
This commit is contained in:
Stuart Thackray 2016-07-02 14:34:54 +02:00
parent 6bbdfe6c41
commit a539c15aaa
3 changed files with 219 additions and 147 deletions

18
.gitignore vendored Normal file
View File

@ -0,0 +1,18 @@
.rebar3
_*
.eunit
*.o
*.beam
*.plt
*.swp
*.swo
.erlang.cookie
ebin
*.log
erl_crash.dump
.rebar
_build
.project
.settings
rebar3.crashdump
rebar.lock

44
README.md Normal file → Executable file
View File

@ -2,7 +2,49 @@
parse and format rfc3339 strings in elixir and erlang
## Installing as a rebar depedancy (erlang)
You install it as a rebar dependency by adding the following in the deps section of rebar.config
```erlang
{rfc3339, {git, "git://github.com/talentdeficit/rfc3339.git", {branch, master}}}
```
## building
```bash
rebar3 compile
```
## running
```bash
rebar3 shell
```
## erlang usage
###### parse_to_local_datetime
```erlang
> rfc3339:parse_to_local_datetime(<<"1996-12-19T16:39:57-08:00">>).
{{1996,12,19},{10,39,57}}
```
###### parse
```erlang
> rfc3339:parse(<<"1937-01-01T12:00:27.87+00:20">>).
{ok,{{1937,1,1},{12,0,27},870000,20}}
```
###### format
```erlang
> rfc3339:format({date(), time()}).
{ok,<<"2016-07-02T14:04:39Z">>}
```
## todo
* everything
-[ ] everything

View File

@ -1,6 +1,7 @@
% vim: sw=4 ts=4 et ft=erlang
-module(rfc3339).
-export([parse/1]).
-export([parse/1,parse_to_local_datetime/1]).
-export([format/1, format/2]).
-export([to_map/1]).
-export([to_time/1, to_time/2]).
@ -25,6 +26,17 @@
-type error() :: badarg | baddate | badtime | badyear | badday | badhour | badminute | badsecond | badusec | badtimezone.
%% -spec parse_to_local_datetime(binary()) -> {date(), time()}
parse_to_local_datetime(Bin) ->
{ok, {Date, Time, _, TZ}} = parse(Bin),
TZSecs = calendar:datetime_to_gregorian_seconds({Date, Time}),
UTCDateTime = calendar:gregorian_seconds_to_datetime(case TZ of
_ when is_integer(TZ) ->
TZSecs + (60*TZ);
_ ->
TZSecs
end),
calendar:universal_time_to_local_time(UTCDateTime).
-spec parse(binary()) -> {ok, {date(), time(), usec(), tz()}} | {error, error()}.
parse(Bin) when is_binary(Bin) -> date(Bin, {undefined, undefined, undefined, undefined});
@ -55,12 +67,12 @@ to_time(Bin, Unit) when is_binary(Bin) ->
mapify({Year, Month, Day}, Time, USec, Tz, Result)
when is_integer(Year), is_integer(Month), is_integer(Day) ->
when is_integer(Year), is_integer(Month), is_integer(Day) ->
mapify(Time, USec, Tz, maps:merge(Result, #{year => Year, month => Month, day => Day}));
mapify(_, _, _, _, _) -> {error, badarg}.
mapify({Hour, Min, Sec}, USec, Tz, Result)
when is_integer(Hour), is_integer(Min), is_integer(Sec) ->
when is_integer(Hour), is_integer(Min), is_integer(Sec) ->
mapify(USec, Tz, maps:merge(Result, #{hour => Hour, min => Min, sec => Sec}));
mapify(_, _, _, _) -> {error, badarg}.
@ -83,10 +95,10 @@ mapify(_) -> {error, badarg}.
-spec format(map() | {date(), time(), usec(), tz()} | datetime() | integer()) -> {ok, binary()} | {error, error()}.
format({Date, Time, USec, Tz})
when is_tuple(Date), is_tuple(Time) ->
when is_tuple(Date), is_tuple(Time) ->
format(mapify(Date, Time, USec, Tz, #{}));
format({Date, Time})
when is_tuple(Date), is_tuple(Time) ->
when is_tuple(Date), is_tuple(Time) ->
format(mapify(Date, Time, undefined, undefined, #{}));
format(Time) when is_integer(Time) ->
%% USec is the greatest fidelity supported. nano seconds are converted lossily
@ -115,7 +127,7 @@ date(_, _Result) ->
%% space
time(_, {{error, Error}, _, _, _}) -> {error, Error};
time(<<Sep, H1, H2, $:, M1, M2, $:, S1, S2, Rest/binary>>, {Date, undefined, undefined, undefined})
when Sep == 16#20 orelse Sep == $t orelse Sep == $T ->
when Sep == 16#20 orelse Sep == $t orelse Sep == $T ->
Hour = to_hour(H1, H2),
Min = to_minute(M1, M2),
Sec = to_second(S1, S2),
@ -130,11 +142,11 @@ usec_or_tz(Rest, Result) -> tz(Rest, Result).
%% next two clauses burn off fractional seconds beyond microsecond precision
usec(<<X, Rest/binary>>, Result, USec, 0)
when X >= $0 andalso X =< $9 ->
when X >= $0 andalso X =< $9 ->
usec(Rest, Result, USec, 0);
%% keep a running acc of usecs
usec(<<X, Rest/binary>>, Result, USec, Multiplier)
when X >= $0 andalso X =< $9 ->
when X >= $0 andalso X =< $9 ->
try list_to_integer([X]) of
N -> usec(Rest, Result, USec + (N * Multiplier), Multiplier div 10)
catch