Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ T, Z, r, and c), `qdate` will handle them for us.
+ `to_unixtime(Date)` - converts any date/time format to a unixtime integer

A **ToTimezone** value of the atom `auto` will automatically determine the
timezone. For example, `to_date(Date, auto)` is exactly the same as
`to_date(Date)`
timezone. For example, `to_date(auto, Date)` is exactly the same as
`to_date(Date)`. The atom `retain` will retain the original timezone as
determined from the input date.

**A Note About Argument Order**: In all cases, `ToTimezone` is optional and if
omitted, will be determined as described below in "Understanding Timezone
Expand Down
63 changes: 39 additions & 24 deletions src/qdate.erl
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@
get_timezone/0,
get_timezone/1,
clear_timezone/0,
clear_timezone/1
clear_timezone/1,
parse_timezone/1
]).

-export([
Expand Down Expand Up @@ -160,14 +161,15 @@ to_string(FormatKey, ToTZ, Disambiguate, Date) when is_atom(FormatKey) orelse is
to_string(Format, ToTZ, Disambiguate, Date) when is_binary(Format) ->
list_to_binary(to_string(binary_to_list(Format), ToTZ, Disambiguate, Date));
to_string(Format, ToTZ, Disambiguate, Date) when is_list(Format) ->
{DateNoTZ, FromTZ} = parse_timezone(Date),
%% it may seem odd that we're ensuring it here, and then again
%% as one of the last steps of the to_date process, but we need
%% the actual name for the strings for the PHP "T" and "e", so
%% we extract the Timezone in case ToTZ is actually a timezone key
%% Then we can pass it on to to_date as well. That way we don't have
%% to do it twice, since it's already ensured.
ActualToTZ = ensure_timezone(ToTZ),
case to_date(ActualToTZ, Disambiguate, Date) of
ActualToTZ = ensure_timezone(ToTZ, FromTZ),
case to_date(ActualToTZ, Disambiguate, Date, DateNoTZ, FromTZ) of
{ambiguous, Standard, Daylight} ->
{ambiguous,
to_string_worker(Format, ActualToTZ, prefer_standard, Standard),
Expand Down Expand Up @@ -264,25 +266,20 @@ nparse(String) ->

to_date(RawDate) ->
to_date(?DETERMINE_TZ, RawDate).

to_date(ToTZ, RawDate) ->
to_date(ToTZ, ?DEFAULT_DISAMBIG, RawDate).

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) ->
to_date(binary_to_list(ToTZ), Disambiguate, RawDate);
to_date(ToTZ, Disambiguate, RawDate) ->
{ExtractedDate, ExtractedTZ} = extract_timezone(RawDate),
{RawDate3, FromTZ} = case try_registered_parsers(RawDate) of
undefined ->
{ExtractedDate, ExtractedTZ};
{ParsedDate,undefined} ->
{ParsedDate,ExtractedTZ};
{ParsedDate,ParsedTZ} ->
{ParsedDate,ParsedTZ}
end,
try raw_to_date(RawDate3) of
to_date(ToTZ, Disambiguate, RawDate) ->
{RawDateNoTZ, FromTZ} = parse_timezone(RawDate),
to_date(ToTZ, Disambiguate, RawDate, RawDateNoTZ, FromTZ).

to_date(ToTZ, Disambiguate, RawDate, RawDateNoTZ, FromTZ) when is_binary(RawDate) ->
to_date(ToTZ, Disambiguate, binary_to_list(RawDate), RawDateNoTZ, FromTZ);
to_date(ToTZ, Disambiguate, RawDate, RawDateNoTZ, FromTZ) when is_binary(RawDateNoTZ) ->
to_date(ToTZ, Disambiguate, RawDate, binary_to_list(RawDateNoTZ), FromTZ);
to_date(ToTZ, Disambiguate, RawDate, RawDateNoTZ, FromTZ) ->
try raw_to_date(RawDateNoTZ) of
D={{_,_,_},{_,_,_}} ->
date_tz_to_tz(D, Disambiguate, FromTZ, ToTZ);
{{Year, Month, Date},{Hour,Minute,Second,_Millis}} ->
Expand All @@ -306,6 +303,19 @@ raw_to_date(Now = {_,_,_}) ->
raw_to_date(Date = {{_,_,_},{_,_,_}}) ->
Date.

parse_timezone(RawDate) when is_binary(RawDate) ->
parse_timezone(binary_to_list(RawDate));
parse_timezone(RawDate) ->
{ExtractedDate, ExtractedTZ} = extract_timezone(RawDate),
case try_registered_parsers(RawDate) of
undefined ->
{ExtractedDate, ExtractedTZ};
{ParsedDate,undefined} ->
{ParsedDate, ExtractedTZ};
{ParsedDate, ParsedTZ} ->
{ParsedDate, ParsedTZ}
end.

get_deterministic_datetime() ->
DateZero = {1970,1,1},
TimeZero = {0,0,0},
Expand Down Expand Up @@ -914,7 +924,7 @@ 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);
date_tz_to_tz(Date, Disambiguate, FromTZ, ToTZ) ->
ActualToTZ = ensure_timezone(ToTZ),
ActualToTZ = ensure_timezone(ToTZ, FromTZ),
case Disambiguate of
prefer_standard ->
localtime:local_to_local(Date, FromTZ, ActualToTZ);
Expand Down Expand Up @@ -951,16 +961,18 @@ get_timezone() ->
get_timezone(Key) ->
qdate_srv:get_timezone(Key).

ensure_timezone(auto) ->
ensure_timezone(retain, FromTZ) ->
FromTZ;
ensure_timezone(auto, _) ->
?DETERMINE_TZ;
ensure_timezone(Key) when is_atom(Key) orelse is_tuple(Key) ->
ensure_timezone(Key, _) when is_atom(Key) orelse is_tuple(Key) ->
case get_timezone(Key) of
undefined -> throw({timezone_key_not_found,Key});
ToTZ -> ToTZ
end;
ensure_timezone(TZ) when is_binary(TZ) ->
ensure_timezone(TZ, _) when is_binary(TZ) ->
binary_to_list(TZ);
ensure_timezone(TZ) when is_list(TZ) ->
ensure_timezone(TZ, _) when is_list(TZ) ->
TZ.

clear_timezone() ->
Expand Down Expand Up @@ -1170,7 +1182,10 @@ tz_tests(_) ->
?_assertEqual(true, between("-1 seconds", os:timestamp(), "+1 seconds")),
?_assertEqual(true, between("60 hours ago", unixtime(), "in 15 days")),
?_assertEqual(false, between("+1 seconds", qdate:to_string("n/j/Y g:ia"), "+2 seconds")),
?_assertEqual(false, between("5 seconds ago","1 second ago"))
?_assertEqual(false, between("5 seconds ago","1 second ago")),

?_assertEqual("CST", to_string("T", retain, "3/7/2013 1:00am CST")),
?_assertEqual({{2013,3,7},{1,0,0}}, to_date(retain, "3/7/2013 1:00am CST"))
]}.


Expand Down