Current section
Files
Jump to
Current section
Files
src/tomerl_datetime.erl
-module(tomerl_datetime).
-export([
new_time/3,
new_time/4,
new_date/3,
new_datetime/2,
new_datetime/3,
with_offset/2,
to_calendar/1,
millisecond/1,
offset/1,
type/1,
format/1
]).
-type year() :: 1000 .. 9999.
-type month() :: 1 .. 12.
-type day() :: 1 .. 31.
-type hour() :: 0 .. 23.
-type minute() :: 0 .. 59.
-type second() :: 0 .. 60.
-type millisecond() :: 0 .. 999.
% Minutes
-type offset() :: z | integer().
-record(date, {
year :: year(),
month :: month(),
day :: day()
}).
-record(time, {
hour :: hour(),
minute :: minute(),
second :: second()
}).
-record(time_ms, {
hour :: hour(),
minute :: minute(),
second :: second(),
millisecond :: millisecond()
}).
-record(datetime, {
date :: date(),
time :: time()
}).
-record(datetime_offset, {
date :: date(),
time :: time(),
offset :: offset()
}).
-opaque date() :: #date{}.
-opaque time() :: #time{} | #time_ms{}.
-opaque datetime() :: #datetime{}.
-opaque datetime_offset() :: #datetime_offset{}.
-type t() :: date() | time() | datetime() | datetime_offset().
-export_type([
date/0,
time/0,
datetime/0,
datetime_offset/0,
year/0,
month/0,
day/0,
hour/0,
minute/0,
second/0,
millisecond/0,
offset/0,
t/0
]).
-spec new_time(hour(), minute(), second()) -> time().
new_time(H, M, S) ->
#time{hour=H, minute=M, second=S}.
-spec new_time(hour(), minute(), second(), millisecond()) -> time().
new_time(H, M, S, Ms) ->
#time_ms{hour=H, minute=M, second=S, millisecond=Ms}.
-spec new_date(year(), month(), day()) -> date().
new_date(Y, M, D) ->
#date{year=Y, month=M, day=D}.
-spec new_datetime(date(), time()) -> datetime().
new_datetime(Date, Time) ->
#datetime{date=Date, time=Time}.
-spec new_datetime(date(), time(), offset()) -> datetime_offset().
new_datetime(Date, Time, Offset) ->
#datetime_offset{date=Date, time=Time, offset=Offset}.
-spec with_offset(datetime(), offset()) -> datetime_offset().
with_offset(#datetime{date=Date, time=Time}, Offset) ->
new_datetime(Date, Time, Offset).
-spec type(_) -> time | date | datetime | datetime_offset | undefined.
type(#time{}) ->
time;
type(#time_ms{}) ->
time;
type(#date{}) ->
date;
type(#datetime{}) ->
datetime;
type(#datetime_offset{}) ->
datetime_offset;
type(_) ->
undefined.
-spec to_calendar(time()) -> calendar:time();
(date()) -> calendar:date();
(datetime()) -> calendar:datetime();
(datetime_offset()) -> calendar:datetime().
to_calendar(#time{hour=H, minute=M, second=S}) ->
{H, M, S};
to_calendar(#time_ms{hour=H, minute=M, second=S}) ->
{H, M, S};
to_calendar(#date{year=Y, month=M, day=D}) ->
{Y, M, D};
to_calendar(#datetime{date=Date, time=Time}) ->
{to_calendar(Date), to_calendar(Time)};
to_calendar(#datetime_offset{date=Date, time=Time}) ->
{to_calendar(Date), to_calendar(Time)}.
-spec offset(datetime_offset()) -> offset().
offset(#datetime_offset{offset=Offset}) ->
Offset;
offset(_) ->
undefined.
-spec millisecond(datetime() | datetime_offset() | time()) -> millisecond().
millisecond(#datetime{time=Time}) ->
millisecond(Time);
millisecond(#datetime_offset{time=Time}) ->
millisecond(Time);
millisecond(#time{}) ->
0;
millisecond(#time_ms{millisecond=Ms}) ->
Ms.
-spec format(datetime() | datetime_offset() | time() | date()) -> iolist().
format(#time{hour=H, minute=M, second=S}) ->
io_lib:format("~2..0B:~2..0B:~2..0B", [H, M, S]);
format(#time_ms{hour=H, minute=M, second=S, millisecond=Ms}) ->
io_lib:format("~2..0B:~2..0B:~2..0B.~3..0B", [H, M, S, Ms]);
format(#date{year=Y, month=M, day=D}) ->
io_lib:format("~4..0B-~2..0B-~2..0B", [Y, M, D]);
format(#datetime{date=Date, time=Time}) ->
[format(Date), $T, format(Time)];
format(#datetime_offset{date=Date, time=Time, offset=z}) ->
[format(Date), $T, format(Time), $Z];
format(#datetime_offset{date=Date, time=Time, offset=Offset}) ->
Sign = if Offset < 0 -> $-; true -> $+ end,
Offset1 = abs(Offset),
Minutes = Offset1 rem 60,
Hours = Offset1 div 60,
Formatted = io_lib:format("~2..0B:~2..0B", [Hours, Minutes]),
[format(Date), $T, format(Time), Sign, Formatted].