diff options
Diffstat (limited to 'lib/stdlib')
-rw-r--r-- | lib/stdlib/doc/src/calendar.xml | 32 | ||||
-rw-r--r-- | lib/stdlib/doc/src/dict.xml | 8 | ||||
-rw-r--r-- | lib/stdlib/doc/src/orddict.xml | 8 | ||||
-rw-r--r-- | lib/stdlib/src/calendar.erl | 53 | ||||
-rw-r--r-- | lib/stdlib/src/escript.erl | 18 | ||||
-rw-r--r-- | lib/stdlib/test/calendar_SUITE.erl | 22 |
6 files changed, 126 insertions, 15 deletions
diff --git a/lib/stdlib/doc/src/calendar.xml b/lib/stdlib/doc/src/calendar.xml index 36f0c03162..f90d8308b6 100644 --- a/lib/stdlib/doc/src/calendar.xml +++ b/lib/stdlib/doc/src/calendar.xml @@ -63,6 +63,14 @@ given as local time, they must be converted to universal time, in order to get the correct value of the elapsed time between epochs. Use of the function <c>time_difference/2</c> is discouraged.</p> + <p>There exists different definitions for the week of the year. + The calendar module contains a week of the year implementation + which conforms to the ISO 8601 standard. Since the week number for + a given date can fall on the previous, the current or on the next + year it is important to provide the information which year is it + together with the week number. The function <c>iso_week_number/0</c> + and <c>iso_week_number/1</c> returns a tuple of the year and the + week number.</p> </description> <section> @@ -154,6 +162,30 @@ time() = {Hour, Minute, Second} </desc> </func> <func> + <name>iso_week_number() -> IsoWeekNumber</name> + <fsummary>Compute the iso week number for the actual date</fsummary> + <type> + <v>IsoWeekNumber = {int(), int()}</v> + </type> + <desc> + <p>This function returns the tuple {Year, WeekNum} representing + the iso week number for the actual date. For determining the + actual date, the function <c>local_time/0</c> is used.</p> + </desc> + </func> + <func> + <name>iso_week_number(Date) -> IsoWeekNumber</name> + <fsummary>Compute the iso week number for the given date</fsummary> + <type> + <v>Date = date()</v> + <v>IsoWeekNumber = {int(), int()}</v> + </type> + <desc> + <p>This function returns the tuple {Year, WeekNum} representing + the iso week number for the given date.</p> + </desc> + </func> + <func> <name>last_day_of_the_month(Year, Month) -> int()</name> <fsummary>Compute the number of days in a month</fsummary> <desc> diff --git a/lib/stdlib/doc/src/dict.xml b/lib/stdlib/doc/src/dict.xml index ebcd2eed09..1695e9d14f 100644 --- a/lib/stdlib/doc/src/dict.xml +++ b/lib/stdlib/doc/src/dict.xml @@ -165,8 +165,8 @@ dictionary() <v>Dict = dictionary()</v> </type> <desc> - <p>This function converts the key/value list <c>List</c> to a - dictionary.</p> + <p>This function converts the <c>Key</c> - <c>Value</c> list + <c>List</c> to a dictionary.</p> </desc> </func> <func> @@ -270,7 +270,7 @@ merge(Fun, D1, D2) -> <v>Dict1 = Dict2 = dictionary()</v> </type> <desc> - <p>Update the a value in a dictionary by calling <c>Fun</c> on + <p>Update a value in a dictionary by calling <c>Fun</c> on the value to get a new value. An exception is generated if <c>Key</c> is not present in the dictionary.</p> </desc> @@ -285,7 +285,7 @@ merge(Fun, D1, D2) -> <v>Dict1 = Dict2 = dictionary()</v> </type> <desc> - <p>Update the a value in a dictionary by calling <c>Fun</c> on + <p>Update a value in a dictionary by calling <c>Fun</c> on the value to get a new value. If <c>Key</c> is not present in the dictionary then <c>Initial</c> will be stored as the first value. For example <c>append/3</c> could be defined diff --git a/lib/stdlib/doc/src/orddict.xml b/lib/stdlib/doc/src/orddict.xml index 08c808f822..9d036f0725 100644 --- a/lib/stdlib/doc/src/orddict.xml +++ b/lib/stdlib/doc/src/orddict.xml @@ -172,8 +172,8 @@ ordered_dictionary() <v>Orddict = ordered_dictionary()</v> </type> <desc> - <p>This function converts the key/value list <c>List</c> to a - dictionary.</p> + <p>This function converts the <c>Key</c> - <c>Value</c> list + <c>List</c> to a dictionary.</p> </desc> </func> <func> @@ -277,7 +277,7 @@ merge(Fun, D1, D2) -> <v>Orddict1 = Orddict2 = ordered_dictionary()</v> </type> <desc> - <p>Update the a value in a dictionary by calling <c>Fun</c> on + <p>Update a value in a dictionary by calling <c>Fun</c> on the value to get a new value. An exception is generated if <c>Key</c> is not present in the dictionary.</p> </desc> @@ -292,7 +292,7 @@ merge(Fun, D1, D2) -> <v>Orddict1 = Orddict2 = ordered_dictionary()</v> </type> <desc> - <p>Update the a value in a dictionary by calling <c>Fun</c> on + <p>Update a value in a dictionary by calling <c>Fun</c> on the value to get a new value. If <c>Key</c> is not present in the dictionary then <c>Initial</c> will be stored as the first value. For example <c>append/3</c> could be defined diff --git a/lib/stdlib/src/calendar.erl b/lib/stdlib/src/calendar.erl index ddc0666f77..57b7c28dee 100644 --- a/lib/stdlib/src/calendar.erl +++ b/lib/stdlib/src/calendar.erl @@ -28,6 +28,8 @@ gregorian_days_to_date/1, gregorian_seconds_to_datetime/1, is_leap_year/1, + iso_week_number/0, + iso_week_number/1, last_day_of_the_month/2, local_time/0, local_time_to_universal_time/1, @@ -70,6 +72,7 @@ -type second() :: 0..59. -type daynum() :: 1..7. -type ldom() :: 28 | 29 | 30 | 31. % last day of month +-type weeknum() :: 1..53. -type t_now() :: {non_neg_integer(),non_neg_integer(),non_neg_integer()}. @@ -77,6 +80,7 @@ -type t_time() :: {hour(),minute(),second()}. -type t_datetime() :: {t_date(),t_time()}. -type t_datetime1970() :: {{year1970(),month(),day()},t_time()}. +-type t_yearweeknum() :: {year(),weeknum()}. %%---------------------------------------------------------------------- @@ -172,6 +176,42 @@ is_leap_year1(Year) when Year rem 400 =:= 0 -> is_leap_year1(_) -> false. +%% +%% Calculates the iso week number for the current date. +%% +-spec iso_week_number() -> t_yearweeknum(). +iso_week_number() -> + {Date, _} = local_time(), + iso_week_number(Date). + + +%% +%% Calculates the iso week number for the given date. +%% +-spec iso_week_number(t_date()) -> t_yearweeknum(). +iso_week_number({Year, Month, Day}) -> + D = date_to_gregorian_days({Year, Month, Day}), + W01_1_Year = gregorian_days_of_iso_w01_1(Year), + W01_1_NextYear = gregorian_days_of_iso_w01_1(Year + 1), + if W01_1_Year =< D andalso D < W01_1_NextYear -> + % Current Year Week 01..52(,53) + {Year, (D - W01_1_Year) div 7 + 1}; + D < W01_1_Year -> + % Previous Year 52 or 53 + PWN = case day_of_the_week(Year - 1, 1, 1) of + 4 -> 53; + _ -> case day_of_the_week(Year - 1, 12, 31) of + 4 -> 53; + _ -> 52 + end + end, + {Year - 1, PWN}; + W01_1_NextYear =< D -> + % Next Year, Week 01 + {Year + 1, 1} + end. + + %% last_day_of_the_month(Year, Month) %% %% Returns the number of days in a month. @@ -377,6 +417,19 @@ dty(Y, D1, D2) when D1 < D2 -> dty(Y, _D1, D2) -> {Y, D2}. +%% +%% The Gregorian days of the iso week 01 day 1 for a given year. +%% +-spec gregorian_days_of_iso_w01_1(year()) -> non_neg_integer(). +gregorian_days_of_iso_w01_1(Year) -> + D0101 = date_to_gregorian_days(Year, 1, 1), + DOW = day_of_the_week(Year, 1, 1), + if DOW =< 4 -> + D0101 - DOW + 1; + true -> + D0101 + 7 - DOW + 1 + end. + %% year_day_to_date(Year, DayOfYear) = {Month, DayOfMonth} %% %% Note: 1 is the first day of the month. diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl index 7cb02afb11..0d2d23180a 100644 --- a/lib/stdlib/src/escript.erl +++ b/lib/stdlib/src/escript.erl @@ -31,7 +31,7 @@ %%----------------------------------------------------------------------- --type mode() :: 'compile' | 'debug' | 'interpret' | 'run'. +-type mode() :: 'native' | 'compile' | 'debug' | 'interpret' | 'run'. -type source() :: 'archive' | 'beam' | 'text'. -record(state, {file :: file:filename(), @@ -304,7 +304,11 @@ parse_and_run(File, Args, Options) -> false -> case lists:member("i", Options) of true -> interpret; - false -> Mode + false -> + case lists:member("n", Options) of + true -> native; + false -> Mode + end end end end, @@ -321,6 +325,14 @@ parse_and_run(File, Args, Options) -> _Other -> fatal("There were compilation errors.") end; + native -> + case compile:forms(FormsOrBin, [report,native]) of + {ok, Module, BeamBin} -> + {module, Module} = code:load_binary(Module, File, BeamBin), + run(Module, Args); + _Other -> + fatal("There were compilation errors.") + end; debug -> case compile:forms(FormsOrBin, [report, debug_info]) of {ok,Module,BeamBin} -> @@ -664,7 +676,7 @@ epp_parse_file2(Epp, S, Forms, Parsed) -> {attribute,Ln,mode,NewMode} -> S2 = S#state{mode = NewMode}, if - NewMode =:= compile; NewMode =:= interpret; NewMode =:= debug -> + NewMode =:= compile; NewMode =:= interpret; NewMode =:= debug; NewMode =:= native -> epp_parse_file(Epp, S2, [Form | Forms]); true -> Args = lists:flatten(io_lib:format("illegal mode attribute: ~p", [NewMode])), diff --git a/lib/stdlib/test/calendar_SUITE.erl b/lib/stdlib/test/calendar_SUITE.erl index 81b0299118..8192d035ca 100644 --- a/lib/stdlib/test/calendar_SUITE.erl +++ b/lib/stdlib/test/calendar_SUITE.erl @@ -28,7 +28,8 @@ day_of_the_week_calibrate/1, leap_years/1, last_day_of_the_month/1, - local_time_to_universal_time_dst/1]). + local_time_to_universal_time_dst/1, + iso_week_number/1]). -define(START_YEAR, 1947). -define(END_YEAR, 2012). @@ -38,7 +39,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [gregorian_days, gregorian_seconds, day_of_the_week, day_of_the_week_calibrate, leap_years, - last_day_of_the_month, local_time_to_universal_time_dst]. + last_day_of_the_month, local_time_to_universal_time_dst, iso_week_number]. groups() -> []. @@ -55,7 +56,6 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. - gregorian_days(doc) -> "Tests that date_to_gregorian_days and gregorian_days_to_date " "are each others inverses from ?START_YEAR-01-01 up to ?END_YEAR-01-01. " @@ -170,6 +170,15 @@ local_time_to_universal_time_dst_x(Config) when is_list(Config) -> {comment,"Bug in mktime() in this OS"} end. +iso_week_number(doc) -> + "Test the iso week number calculation for all three possibilities." + " When the date falls on the last week of the previous year," + " when the date falls on a week within the given year and finally," + " when the date falls on the first week of the next year."; +iso_week_number(suite) -> + []; +iso_week_number(Config) when is_list(Config) -> + ?line check_iso_week_number(). %% %% LOCAL FUNCTIONS @@ -259,7 +268,12 @@ check_last_day_of_the_month({SYr, SMon}, {EYr, EMon}) when SYr < EYr -> check_last_day_of_the_month(_, _) -> ok. - +%% check_iso_week_number +%% +check_iso_week_number() -> + ?line {2004, 53} = calendar:iso_week_number({2005, 1, 1}), + ?line {2007, 1} = calendar:iso_week_number({2007, 1, 1}), + ?line {2009, 1} = calendar:iso_week_number({2008, 12, 29}). |