1%%% Copyright (C) 2009 Enrique Marcote, Miguel Rodriguez 2%%% All rights reserved. 3%%% 4%%% Redistribution and use in source and binary forms, with or without 5%%% modification, are permitted provided that the following conditions are met: 6%%% 7%%% o Redistributions of source code must retain the above copyright notice, 8%%% this list of conditions and the following disclaimer. 9%%% 10%%% o Redistributions in binary form must reproduce the above copyright notice, 11%%% this list of conditions and the following disclaimer in the documentation 12%%% and/or other materials provided with the distribution. 13%%% 14%%% o Neither the name of ERLANG TRAINING AND CONSULTING nor the names of its 15%%% contributors may be used to endorse or promote products derived from this 16%%% software without specific prior written permission. 17%%% 18%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19%%% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20%%% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21%%% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22%%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23%%% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24%%% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25%%% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26%%% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27%%% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28%%% POSSIBILITY OF SUCH DAMAGE. 29-module(cl_calendar). 30 31%%% EXTERNAL EXPORTS 32-export([day/0, 33 day/1, 34 day/3, 35 day_of_current_week_to_date/1, 36 day_of_next_week_to_date/1, 37 format_day/1, 38 format_month/1, 39 format_rfc2109/1, 40 format_rfc2109/2, 41 local_time/0, 42 parse/1, 43 time_difference/2, 44 tstamp/0, 45 tstamp/1, 46 tstamp_to_local_time/1, 47 valid_time/1, 48 valid_time/3, 49 week/0, 50 week/1, 51 week/3]). 52 53%%% MACROS 54-define(JANUARY_1ST_1970, 62167219200). 55-define(SEPARATORS, [$/, $-, $_, $:, $ ]). 56 57%%%----------------------------------------------------------------------------- 58%%% EXTERNAL EXPORTS 59%%%----------------------------------------------------------------------------- 60day() -> 61 day(date()). 62 63day({Year, Month, Day}) -> 64 day(Year, Month, Day). 65 66day(Year, Month, Day) -> 67 January1st = calendar:date_to_gregorian_days(Year, 1, 1), 68 calendar:date_to_gregorian_days(Year, Month, Day) - January1st + 1. 69 70 71day_of_current_week_to_date(DayNumber) -> 72 CurrentDayNumber = calendar:date_to_gregorian_days(date()), 73 CurrentDayOfWeek = calendar:day_of_the_week(date()), 74 calendar:gregorian_days_to_date( 75 CurrentDayNumber + DayNumber - CurrentDayOfWeek). 76 77 78day_of_next_week_to_date(DayNumber) -> 79 CurrentDayNumber = calendar:date_to_gregorian_days(date()), 80 CurrentDayOfWeek = calendar:day_of_the_week(date()), 81 calendar:gregorian_days_to_date( 82 CurrentDayNumber + DayNumber + 7 - CurrentDayOfWeek). 83 84 85format_day(1) -> 86 "Mon"; 87format_day(2) -> 88 "Tue"; 89format_day(3) -> 90 "Wed"; 91format_day(4) -> 92 "Thu"; 93format_day(5) -> 94 "Fri"; 95format_day(6) -> 96 "Sat"; 97format_day(7) -> 98 "Sun". 99 100 101format_month(1) -> 102 "Jan"; 103format_month(2) -> 104 "Feb"; 105format_month(3) -> 106 "Mar"; 107format_month(4) -> 108 "Apr"; 109format_month(5) -> 110 "May"; 111format_month(6) -> 112 "Jun"; 113format_month(7) -> 114 "Jul"; 115format_month(8) -> 116 "Aug"; 117format_month(9) -> 118 "Sep"; 119format_month(10) -> 120 "Oct"; 121format_month(11) -> 122 "Nov"; 123format_month(12) -> 124 "Dec". 125 126 127format_rfc2109(DateTime) -> 128 format_rfc2109(DateTime, "GMT"). 129 130format_rfc2109({{Year, Month, Day}, {Hour, Min, Sec}}, Timezone) -> 131 % Estrange but much faster than using io_lib 132 FDay = format_day(calendar:day_of_the_week({Year, Month, Day})), 133 FMonth = format_month(Month), 134 Time = [pad(Hour), ":", pad(Min), ":", pad(Sec), " ", Timezone], 135 lists:concat([FDay, ", ", pad(Day), "-", FMonth, "-", Year, " " | Time]). 136 137 138local_time() -> 139 % Estrange but much faster than using io_lib 140 {{Year, Month, Day}, {Hour, Min, Sec}} = erlang:localtime(), 141 LocalTime = Sec + (Min * 100) + (Hour * 10000) + (Day * 1000000) + 142 (Month * 100000000) + (Year * 10000000000), 143 integer_to_list(LocalTime). 144 145 146parse([H1, H2, _, M1, M2, _, S1, S2]) -> 147 Hour = list_to_integer([H1, H2]), 148 Min = list_to_integer([M1, M2]), 149 Sec = list_to_integer([S1, S2]), 150 true = valid_time(Hour, Min, Sec), 151 {Hour, Min, Sec}; 152parse([Y1, Y2, Y3, Y4, _, M1, M2, _, D1, D2]) -> 153 Year = list_to_integer([Y1, Y2, Y3, Y4]), 154 Month = list_to_integer([M1, M2]), 155 Day = list_to_integer([D1, D2]), 156 true = calendar:valid_date(Year, Month, Day), 157 {Year, Month, Day}; 158parse([Y1, Y2, Y3, Y4, S1, M1, M2, S2, D1, D2, _ | Time]) -> 159 {parse([Y1, Y2, Y3, Y4, S1, M1, M2, S2, D1, D2]), parse(Time)}. 160 161 162time_difference(Time1, Time2) -> 163 calendar:time_to_seconds(Time1) - calendar:time_to_seconds(Time2). 164 165 166tstamp() -> 167 tstamp(erlang:localtime()). 168 169tstamp(Time) -> 170 calendar:datetime_to_gregorian_seconds(Time) - ?JANUARY_1ST_1970. 171 172 173tstamp_to_local_time(Tstamp) -> 174 calendar:gregorian_seconds_to_datetime(Tstamp + ?JANUARY_1ST_1970). 175 176 177valid_time({H, M, S}) -> 178 valid_time(H, M, S). 179 180valid_time(H, M, S) when H >= 0, H < 24, M >= 0, M < 60, S >= 0, S < 60 -> 181 true; 182valid_time(_, _, _) -> 183 false. 184 185 186week() -> 187 week(date()). 188 189week({Year, Month, Day}) -> 190 week(Year, Month, Day). 191 192week(Year, Month, Day) -> 193 DaysUntil1stSunday = 7 - calendar:day_of_the_week(Year, 1, 1) + 1, 194 DaysSince1stSunday = day(Year, Month, Day) - DaysUntil1stSunday, 195 if 196 (DaysSince1stSunday rem 7) > 0 -> 197 (DaysSince1stSunday div 7) + 1; 198 true -> 199 (DaysSince1stSunday div 7) 200 end. 201 202%%%----------------------------------------------------------------------------- 203%%% INTERNAL FUNCTIONS 204%%%----------------------------------------------------------------------------- 205pad(N) when N > 9 -> 206 N; 207pad(N) -> 208 [$0 | integer_to_list(N)]. 209