Created
May 2, 2021 17:18
-
-
Save auxiliaire/d01c2e496beec6d189a6b8a78d162ca5 to your computer and use it in GitHub Desktop.
Some basic functions for a Gregorian calendar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -module(gregorian). | |
| -export([ | |
| days/0, | |
| months/0, | |
| dayTuples/0, | |
| monthTuples/0, | |
| dayOfWeek/1, | |
| monthOfYear/1, | |
| isLeap/1, | |
| daysOfMonth/2, | |
| daysOfYear/1, | |
| prev/2, | |
| next/2, | |
| prevMonth/1, | |
| nextMonth/1, | |
| toDays/1, | |
| toDays/2, | |
| toDays/3, | |
| daysBetween/2, | |
| daysSince/3 | |
| ]). | |
| days() -> [ mon, tue, wed, thu, fri, sat, sun ]. | |
| months() -> [ jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec ]. | |
| dayTuples() -> lists:zip(lists:seq(1, 7), days()). | |
| monthTuples() -> lists:zip(lists:seq(1, 12), months()). | |
| dayOfWeek(N) when is_integer(N) -> lists:keyfind(N, 1, dayTuples()); | |
| dayOfWeek(N) when is_atom(N) -> lists:keyfind(N, 2, dayTuples()). | |
| monthOfYear(N) when is_integer(N) -> lists:keyfind(N, 1, monthTuples()); | |
| monthOfYear(N) when is_atom(N) -> lists:keyfind(N, 2, monthTuples()). | |
| isLeap(Y) -> | |
| if Y rem 400 =:= 0 -> true | |
| ; Y rem 100 =:= 0 -> false | |
| ; Y rem 4 =:= 0 -> true | |
| ; true -> false | |
| end. | |
| daysOfMonth(M, Y) when M =:= feb -> | |
| case isLeap(Y) of | |
| true -> 29; | |
| false -> 28 | |
| end; | |
| daysOfMonth(M, _) when true -> | |
| case lists:member(M, [ apr, jun, sep, nov ]) of | |
| true -> 30; | |
| false -> 31 | |
| end. | |
| daysOfYear(Y) -> lists:sum([ daysOfMonth(M, Y) || M <- months() ]). | |
| prev(E, [ H | T ]) -> | |
| case E =:= H of | |
| true -> lists:last(T); | |
| false -> lists:last(lists:takewhile(fun(X) -> X =/= E end, [ H | T ])) | |
| end. | |
| next(E, L) -> | |
| case E =:= lists:last(L) of | |
| true -> hd(L); | |
| false -> hd(tl(lists:dropwhile(fun(X) -> X =/= E end, L))) | |
| end. | |
| prevMonth(M) -> prev(M, months()). | |
| nextMonth(M) -> next(M, months()). | |
| %% Real Gregorian days, not ISO standard Year 0 BS! | |
| toDays(Y, M, D) -> D - 1 + toDays(Y, M). | |
| toDays(Y, M) when M =:= jan -> toDays(Y); | |
| toDays(Y, M) when true -> | |
| P = prevMonth(M), | |
| daysOfMonth(P, Y) + toDays(Y, P). | |
| toDays(Y) when Y =< 1 -> 0; | |
| toDays(Y) when true -> daysOfYear(Y) + toDays(Y - 1). | |
| daysBetween({Y1, M1, D1}, {Y2, M2, D2}) -> toDays(Y2, M2, D2) - toDays(Y1, M1, D1). | |
| daysSince(Y, M, D) -> | |
| {{CY, CMN, CD}, _} = calendar:now_to_local_time(erlang:timestamp()), | |
| CM = element(2, monthOfYear(CMN)), | |
| daysBetween({Y, M, D}, {CY, CM, CD}). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment