/* Some date utils in Picat. This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ module date_utils. % import util. % import cp. main => go. go => nl. % % Day of week, Sakamoto's method % http://en.wikipedia.org/wiki/Weekday_determination#Sakamoto.27s_Method % dow(Y, M, D) = R => T = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4], if M < 3 then Y := Y - 1 end, R = (Y + Y // 4 - Y // 100 + Y // 400 + T[M] + D) mod 7. % max_days(Year,Month) = Days => % if member(Month, [1,3,5,7,8,10,12]) then % Days = 31 % elseif member(Month,[4,6,9,11]) then % Days = 30 % else % if leap_year(Year) then % Days = 29 % else % Days = 28 % end % end. leap_year(Year) => (Year mod 4 == 0, Year mod 100 != 0) ; Year mod 400 == 0. % % http://en.wikipedia.org/wiki/Julian_day % gregorian2julian % g2j(Year,Month,Day) = JD => A = floor((14-Month) / 12), % 1 for Jan or Feb, 0 for other months Y = Year + 4800 - A, M = Month + 12*A - 3, % 0 for Mars, 11 for Feb JD = Day + floor( (153*M + 2) / 5) + 365*Y + floor(Y/4) - floor(Y / 100) + floor(Y / 400) - 32045. % % julian2gregorian % j2g(JD) = Date => Y=4716, V=3, J=1401, U=5, M=2, S=153, N=12, W=2, R=4, B=274277, P=1461, C= -38, F = JD + J + (((4 * JD + B) div 146097) * 3) div 4 + C, E = R * F + V, G = mod(E, P) div R, H = U * G + W, Day = (mod(H, S)) div U + 1, Month = mod(H div S + M, N) + 1, Year = (E div P) - Y + (N + M - Month) div N, Date = [Year,Month,Day]. % for the alternative approach max_days_in_month(Year,Month) = Days => if member(Month, [1,3,5,7,8,10,12]) then Days = 31 elseif member(Month,[4,6,9,11]) then Days = 30 else if leap_year(Year) then Days = 29 else Days = 28 end end.