Code: Select all
{===============================================================}
{ Weekday Calculator }
{---------------------------------------------------------------}
{ Author: Gamall Wednesday Ida }
{ Mail: gamall.ida@gmail.com }
{ Web: gamall-ida.com }
{===============================================================}
{===============================================================}
{ What is it ? }
{===============================================================}
This program computes how much time has elapsed between two
dates, and which day of the week a specific date is. Most
programs doing that kind of thing only support a limited range
of dates, like years 1700-3000 or so. This is not the case here:
dates are supported well beyond the range where our calendar
makes sense.
{===============================================================}
{ How do I use it ? }
{===============================================================}
The help text, displayed when the program is run without
arguments, covers it all:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
** Weekday Calculator
** by Gamall Wednesday Ida
** email : gamall.ida@gmail.com
** web : gamall-ida.com
Usage :
./weekday -day <day> <month> <year>
> returns day of the week
./weekday -ela <d1> <m1> <y1> <d2> <m2> <y2>
> returns days elapsed betweed two dates
Example:
./weekday -day 21 10 1985 --> Monday
./weekday -ela 1 1 1900 21 10 1985 --> 31339
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{===============================================================}
{ Running it }
{===============================================================}
This program has been written in O'Caml. It is in fact my very
first program in this language. A 'Hello World', so to speak,
but I release it because it can actually be mildly useful :P
Three files are provided :
-> 'weekday' : Linux executable, compiled under Ubuntu 7.04.
-> 'weekday.exe' : Windows executable. Will run fine under Linux
with Wine.
-> 'weekday.bytecode' : OCaml universal bytecode. Will run on
any platform with ocamlrun.
The source code, 'weekday.ml', is also shipped. It is released
under the GNU General Public License. See here
<http://www.gnu.org/copyleft/gpl.html> for more information.
{===============================================================}
{ END OF FILE }
{===============================================================}
+-----------------------------+
| File generated with 'GaTeX',|
| an ASCII typesetting system |
| by Gamall Wednesday Ida. |
| http://gamall-ida.com |
+-----------------------------+
Build: Wed Oct 24 21:31:07 2007
File : f:readme.GaTeX.source
Code: Select all
(*
Weekday Calculator
by Gamall Wednesday Ida
gamall-ida.com
Note: This is my very first O'Caml program :-))
*)
(* numerical date *)
type date = int * int * int ;;
let getDay = function
d, m, y -> d;;
let getMonth = function
d, m, y -> m;;
let getYear = function
d, m, y -> y;;
(* Day pretty print *)
let printDay = function
0 -> "Monday"
| 1 -> "Tuesday"
| 2 -> "Wednesday"
| 3 -> "Thursday"
| 4 -> "Friday"
| 5 -> "Saturday"
| 6 -> "Sunday"
| _ -> failwith "Error: trying to print out-of bounds weekday !";;
(* is this year a leap year ? *)
let isLeap y =
((y mod 4 = 0) & (y mod 100 <> 0)) || (y mod 400 = 0);;
(* how many days in this specific month ? *)
let daysInMonth m y = match m with
| 1 | 3 | 5 | 7 | 8 | 10 | 12 -> 31
| 2 -> if isLeap y then 29 else 28
| _ when (m <= 12 & m > 0) -> 30
| _ -> failwith("Error : Incorrect month !");;
(* how many days in this year ? *)
let daysInYear y = if isLeap y then 366 else 365;;
(* is this date valid ? *)
let isValid adate =
let d = getDay adate and m = getMonth adate and y = getYear adate in
d > 0 & m > 0 & m <= 12 & d <= daysInMonth m y ;;
(* is a date strictly anterior to another ? *)
let ( << ) d dd =
let cy = getYear d < getYear dd and cm = getMonth d < getMonth dd and cd = getDay d < getDay dd in
cy || (getYear d = getYear dd & cm) || ( (getYear d = getYear dd) & (getMonth d = getMonth dd) & cd );;
(* get next day *)
let succ = function
d, m, y when isValid (d+1, m, y) -> d+1, m, y
| d, m, y when isValid (1, m+1, y) -> 1, m+1, y
| d, m, y -> 1, 1, y+1;;
(* what's my position in this year ? *)
let rec posInYear = function
|0, 0, y -> 0
|31,12,y -> daysInYear y
|0, m, y -> (daysInMonth m y) + posInYear (0, m-1, y)
|d, m, y -> d + posInYear (0, m-1, y);;
(* how many days between two dates ? *)
let rec elapsed d dd =
if d = dd then 0 else
if dd << d then (- elapsed dd d) else
let rec ie d dd acc =
if d = dd then acc else
if getYear dd > getYear d then ie d (31, 12, (getYear dd) - 1) (acc + (posInYear dd)) else
ie (succ d) dd (acc+1)
in
ie (succ d) dd 1 ;;
(* which day of the week is this date ? *)
let dayOfWeek adate =
let n = (elapsed (21, 10,1985) adate ) mod 7 in
if n < 0 then printDay (n+7) else
printDay n;;
(*************************************************************)
open Printf
let av = Sys.argv;;
let ac = Array.length av;;
let _ =
if ac = 1 then (
printf "\n** Weekday Calculator\n";
printf "** by Gamall Wednesday Ida\n";
printf "** email : gamall.ida@gmail.com\n";
printf "** web : gamall-ida.com\n\n";
printf "Usage :\n\n";
printf "%s -day <day> <month> <year>\n" av.(0);
printf "> returns day of the week\n\n";
printf "%s -ela <d1> <m1> <y1> <d2> <m2> <y2>\n" av.(0);
printf "> returns days elapsed betweed two dates\n\n";
printf "Example:\n\n";
printf "%s -day 21 10 1985 --> Monday\n" av.(0);
printf "%s -ela 1 1 1900 21 10 1985 --> 31339\n\n" av.(0);
) else (
if av.(1) = "-day" then (
if ac <> 5 then failwith "ERROR: Incorrect number of arguments !";
let da = (int_of_string av.(2), int_of_string av.(3), int_of_string av.(4)) in (
if not (isValid da) then failwith "ERROR: Invalid date !";
printf "%s\n" (dayOfWeek da);
);
)else if av.(1) = "-ela" then (
if ac <> 8 then failwith "ERROR: Incorrect number of arguments !";
let da = (int_of_string av.(2), int_of_string av.(3), int_of_string av.(4)) and
db = (int_of_string av.(5), int_of_string av.(6), int_of_string av.(7)) in (
if (not (isValid da) || not (isValid db)) then failwith "ERROR: Invalid date !";
printf "%d\n" (elapsed da db);
);
) else failwith "ERROR: Unrecognized command !";
)
;;