123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660(**************************************************************************)(* *)(* This file is part of Calendar. *)(* *)(* Copyright (C) 2003-2011 Julien Signoles *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License version 2.1 as published by the *)(* Free Software Foundation, with a special linking exception (usual *)(* for Objective Caml libraries). *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR *)(* *)(* See the GNU Lesser General Public Licence version 2.1 for more *)(* details (enclosed in the file LGPL). *)(* *)(* The special linking exception is detailled in the enclosed file *)(* LICENSE. *)(**************************************************************************)moduletypeS=sigtypetvalfprint:string->Format.formatter->t->unitvalprint:string->t->unitvaldprint:t->unitvalsprint:string->t->stringvalto_string:t->stringvalfrom_fstring:string->string->tvalfrom_string:string->tendletday_name=ref(function|Date.Sun->"Sunday"|Date.Mon->"Monday"|Date.Tue->"Tuesday"|Date.Wed->"Wednesday"|Date.Thu->"Thursday"|Date.Fri->"Friday"|Date.Sat->"Saturday")letname_of_dayd=!day_namedletshort_name_of_dayd=letd=name_of_daydintryString.subd03withInvalid_argument_->dletmonth_name=ref(function|Date.Jan->"January"|Date.Feb->"February"|Date.Mar->"March"|Date.Apr->"April"|Date.May->"May"|Date.Jun->"June"|Date.Jul->"July"|Date.Aug->"August"|Date.Sep->"September"|Date.Oct->"October"|Date.Nov->"November"|Date.Dec->"December")letname_of_monthm=!month_namemletshort_name_of_monthm=letm=name_of_monthmintryString.subm03withInvalid_argument_->mtypepad=|Zero|Blank|Empty|Uppercase(* [k] should be a power of 10. *)letprint_numberfmtpadkn=assert(k>0);letrecauxkn=letfillfmt=function|Zero->Format.pp_print_intfmt0|Blank->Format.pp_print_charfmt' '|Empty|Uppercase->()inifk=1thenFormat.pp_print_intfmtnelsebeginifn<kthenfillfmtpad;aux(k/10)nendinifn<0thenFormat.pp_print_charfmt'-';auxk(absn)letbad_formats=raise(Invalid_argument("bad format: "^s))letnot_matchfs=raise(Invalid_argument(s^" does not match the format "^f))letgen_month_of_nameffmtname=letrecauxi=ifi=0thennot_matchfmtnameelseiff(Date.month_of_inti)=namethenielseaux(i-1)inaux12letmonth_of_name=gen_month_of_namename_of_month"%b"letmonth_of_short_name=gen_month_of_nameshort_name_of_month"%B"letgen_day_of_nameffmtname=letrecauxi=ifi=0thennot_matchfmtnameelseiff(Date.day_of_inti)=namethenielseaux(i-1)inaux7letday_of_name=gen_day_of_namename_of_day"%a"letday_of_short_name=gen_day_of_nameshort_name_of_day"%A"letword_regexp=ref(Re.Str.regexp"[a-zA-Z]+")letset_word_regexpr=word_regexp:=rtype'asecond_builder=|Intof(int->int->int->int->int->int->'a)|Floatof(int->int->int->int->int->float->'a)(* [Make] creates a printer from a small set of functions. *)moduleMake(X:sigtypetvalmake:tsecond_buildervalfrom_business:Date.year->int->Date.day->tvaldefault_format:stringvalhour:t->intvalminute:t->intvalsecond:t->intvalday_of_week:t->Date.dayvalday_of_month:t->intvalday_of_year:t->intvalweek:t->intvalmonth:t->Date.monthvalyear:t->intvalcentury:t->intvalseconds_since_1970:t->intend)=structtypet=X.tletshort_intervalh=leth=Lazy.forcehmod12inifh=0then12elsehletfprintffmtx=letlen=String.lengthfinletweekday=lazy(name_of_day(X.day_of_weekx))inletsweekday=lazy(short_name_of_day(X.day_of_weekx))inletday_of_week=lazy(Date.int_of_day(X.day_of_weekx))inletmonth_name=lazy(name_of_month(X.monthx))inletsmonth_name=lazy(short_name_of_month(X.monthx))inletint_month=lazy(Date.int_of_month(X.monthx))inletday_of_month=lazy(X.day_of_monthx)inletday_of_year=lazy(X.day_of_yearx)inletweek=lazy(X.weekx)inletyear=lazy(X.yearx)inletsyear=(* work only if year in (0..9999) *)lazy(Lazy.forceyearmod100)inletcentury=lazy(X.centuryx)inlethour=lazy(X.hourx)inletshour=lazy(short_intervalhour)inletminute=lazy(X.minutex)inletsecond=lazy(X.secondx)inletapm=lazy(ifLazy.forcehourmod24<12then"AM"else"PM")inlettz=lazy(Time_Zone.from_gmt())inletseconds_since_1970=lazy(X.seconds_since_1970x)inletprint_charc=Format.pp_print_charfmtcinletprint_intpadkn=print_numberfmtpadk(Lazy.forcen)inletprint_stringpads=letpads=matchpadwith|Uppercase->String.uppercase_asciis|Empty|Zero|Blank->sinFormat.pp_print_stringfmt(pad(Lazy.forces))inletprint_timepadh=print_intpad10h;print_char':';print_intpad10minute;print_char':';print_intpad10secondinletrecparse_optionipad=letparse_charc=letjump=ref0inbeginmatchcwith|'%'->print_char'%'|'a'->print_stringpadsweekday|'A'->print_stringpadweekday|'b'|'h'->print_stringpadsmonth_name|'B'->print_stringpadmonth_name|'c'->print_stringpadsweekday;print_char' ';print_stringpadsmonth_name;print_char' ';print_intpad10day_of_month;print_char' ';print_timepadhour;print_char' ';print_intpad1000year|'C'->print_intpad10century|'d'->print_intpad10day_of_month|'D'->print_intpad10int_month;print_char'/';print_intpad10day_of_month;print_char'/';print_intpad10syear|'e'->print_intBlank10day_of_month|'F'|'i'->print_intpad1000year;print_char'-';print_intpad10int_month;print_char'-';print_intpad10day_of_month|'H'->print_intpad10hour;|'I'->print_numberfmtpad10(short_intervalhour)|'j'->print_intpad100day_of_year|'k'->print_intBlank10hour|'l'->print_numberfmtBlank10(short_intervalhour)|'m'->print_intpad10int_month|'M'->print_intpad10minute|'n'->print_char'\n'|'p'->print_stringpadapm|'P'->Format.pp_print_stringfmt(String.lowercase_ascii(Lazy.forceapm))|'r'->print_timepadshour;print_char' ';print_stringpadapm|'s'->print_intpad1seconds_since_1970|'R'->print_intpad10hour;print_char':';print_intpad10minute|'S'->print_intpad10second|'t'->print_char'\t'|'T'->print_timepadhour|'V'|'W'->print_intpad10week|'w'->print_intEmpty1day_of_week|'y'->print_intpad10syear|'Y'->print_intpad1000year|'z'->ifLazy.forcetz>=0thenprint_char'+';print_intpad10tz;print_numberfmtZero100|':'->letidx=tryRe.Str.search_forward(Re.Str.regexp"z\\|:z\\|::z")f(i+1)withNot_found->bad_formatfinletnext=Re.Str.matched_stringfinifidx<>i+1thenbad_formatf;ifLazy.forcetz>=0thenprint_char'+';print_intpad10tz;letprint_block()=print_char':';print_numberfmtZero100injump:=String.lengthnext;(matchnextwith|"z"->print_block()|":z"->print_block();print_block()|"::z"->()|_->assertfalse);|c->bad_format("%"^String.make1c)end;parse_format(i+1+!jump)inassert(i<=len);ifi=lenthenbad_formatf;(* else *)letpadp=ifpad<>Zerothenbad_formatf;(* else *)parse_option(i+1)pinmatchf.[i]with|'0'->padZero|'-'->padEmpty|'_'->padBlank|'^'->padUppercase|c->parse_charcandparse_formati=assert(i<=len);ifi=lenthen()elsematchf.[i]with|'%'->parse_option(i+1)Zero|c->Format.pp_print_charfmtc;parse_format(i+1)inparse_format0;Format.pp_print_flushfmt()letprintf=fprintfFormat.std_formatterletdprint=printX.default_formatletsprintfd=letbuf=Buffer.create15inletfmt=Format.formatter_of_bufferbufinfprintffmtd;Buffer.contentsbufletto_string=sprintX.default_formatletfrom_fstringfs=letdelayed_computations=ref[]inletday_of_week,week=refmin_int,refmin_intinletyear,month,day=refmin_int,refmin_int,refmin_intinlethour,minute,second,pm=refmin_int,refmin_int,ref(floatmin_int),ref0inlettz=ref0inletfrom_biz()=if!week=-1||!year=-1thenbad_format(f^" (either week or year is not provided)");letd=X.from_business!year!week(Date.day_of_int!day_of_week)inyear:=X.yeard;month:=Date.int_of_month(X.monthd);day:=X.day_of_monthdinletj=ref0inletlenf=String.lengthfinletlens=String.lengthsinletread_charc=if!j>=lens||s.[!j]!=cthennot_matchfs;incrjinletread_numbern=letjn=!j+ninifjn>lensthennot_matchfs;letres=tryint_of_string(String.subs!jn)withFailure_->not_matchfsinj:=jn;resinletread_word?(regexp=(!word_regexp))()=letjn=tryRe.Str.search_forwardregexps!jwithNot_found->not_matchfsinifjn<>!jthennot_matchfs;letw=Re.Str.matched_stringsinj:=jn+String.lengthw;winletread_float=letregexp=Re.Str.regexp"[0-9][0-9]\\(\\.[0-9]*\\)?"infun()->tryfloat_of_string(read_word~regexp())withFailure_->not_matchfsinletparse_a()=ignore(day_of_short_name(read_word()))inletparse_b()=month:=month_of_short_name(read_word())inletparse_d()=day:=read_number2inletparse_H()=hour:=read_number2inletparse_I()=hour:=read_number2inletparse_m()=month:=read_number2inletparse_M()=minute:=read_number2inletparse_p()=matchread_word()with|"AM"->pm:=0|"PM"->pm:=12|s->not_match"%p"("\""^s^"\"")inletparse_S()=matchX.makewith|Int_->second:=float(read_number2)|Float_->second:=read_float()inletparse_Vfmt=letn=read_number2inifn<1||n>53thennot_matchfmt(string_of_intn);week:=ninletparse_y()=year:=read_number2+1900inletparse_Y()=year:=read_number4inletparse_tz()=letsign=matchread_word~regexp:(Re.Str.regexp"[\\+-]")()with|"+"->-1|"-"->1|_->assertfalseinletn=read_number2intz:=sign*n;inletrecparse_optioni=assert(i<=lenf);ifi=lenfthenbad_formatf;(* else *)letjump=ref0in(matchf.[i]with|'%'->read_char'%'|'a'->parse_a()|'A'->ignore(day_of_short_name(read_word()))|'b'->parse_b()|'B'->month:=month_of_name(read_word())|'c'->parse_a();read_char' ';parse_b();read_char' ';parse_d();read_char' ';parse_H();read_char':';parse_M();read_char':';parse_S();read_char' ';parse_Y()|'C'->ignore(read_number2)|'d'->parse_d()|'D'->parse_m();read_char'/';parse_d();read_char'/';parse_y()|'F'|'i'->parse_Y();read_char'-';parse_m();read_char'-';parse_d()|'h'->parse_b()|'H'->parse_H()|'I'->parse_I()|'j'->letn=read_number3inifn<1||n>366thennot_match"%j"(string_of_intn);delayed_computations:=(fun()->if!year=-1thenbad_format"%j (year not provided)";letd=Date.from_day_of_year!yearninmonth:=Date.int_of_month(Date.monthd);day:=Date.day_of_monthd)::!delayed_computations|'m'->parse_m()|'M'->parse_M()|'n'->read_char'\n'|'p'->parse_p()|'P'->(matchread_word()with|"am"->pm:=0|"pm"->pm:=12|s->not_match"%P"("\""^s^"\""))|'r'->parse_I();read_char':';parse_M();read_char':';parse_S();read_char' ';parse_p()|'R'->parse_H();read_char':';parse_M()|'S'->parse_S()|'t'->read_char'\t'|'T'->parse_H();read_char':';parse_M();read_char':';parse_S()|'V'->parse_V"%V"|'w'->letn=read_number1inifn<1||n>7thennot_match"%w"(string_of_intn);day_of_week:=n;delayed_computations:=from_biz::!delayed_computations;|'W'->parse_V"%W"|'y'->parse_y()|'Y'->parse_Y()|'z'->parse_tz();ignore(read_number2)|':'->letrecdotacci=matchf.[i]with|':'->ifacc=3thenbad_format"%::::"elsedot(acc+1)(i+1)|'z'->acc|c->bad_format("%:"^String.make1c)inletnb_dots=dot1(i+1)injump:=nb_dots;letnext=String.makenb_dots':'^"z"inparse_tz();letread_block()=read_char':';ignore(read_number2)in(matchnextwith|":z"->read_block()|"::z"->read_block();read_block()|":::z"->()(* the only available precision is "hh" like "%z" *)|_->assertfalse)|c->bad_format("%"^String.make1c));parse_format(i+1+!jump)andparse_formati=assert(i<=lenf);ifi=lenfthenbeginif!j!=lensthennot_matchfsendelsematchf.[i]with|'%'->parse_option(i+1)|c->read_charc;parse_format(i+1)inparse_format0;List.iter(funf->f())!delayed_computations;letbuildmk=mk!year!month!day(!hour+!pm+!tz)!minuteinmatchX.makewith|Intf->buildf(Utils.Float.round!second)|Floatf->buildf!secondletfrom_string=from_fstringX.default_formatendletcannot_create_eventkindargs=ifList.exists((=)min_int)argsthenraise(Invalid_argument("Cannot create the "^kind))moduleDate=Make(structincludeDateletmakeymd___=cannot_create_event"date"[y;m;d];makeymdletmake=Intmakeletdefault_format="%i"lethour_=bad_format"hour"letminute_=bad_format"minute"letsecond_=bad_format"second"letcenturyd=century(yeard)letseconds_since_1970_=bad_format"seconds_since_1970"end)moduleDatePrinter=DatemoduleTime=Make(structincludeTimeletmake___hms=cannot_create_event"time"[h;m;s];makehmsletmake=Intmakeletdefault_format="%T"letfrom_business___=bad_format"from_business"letday_of_week_=bad_format"day_of_week"letday_of_month_=bad_format"day_of_month"letday_of_year_=bad_format"day_of_year"letweek_=bad_format"week"letmonth_=bad_format"month"letint_month_=bad_format"int_month"letyear_=bad_format"year"letcentury_=bad_format"century"letseconds_since_1970_=bad_format"seconds_since_1970"end)moduleTimePrinter=TimemoduleFtime=Make(structincludeFtimeletmake___hms=cannot_create_event"time"[h;m;Utils.Float.rounds];makehmsletmake=Floatmakeletsecondx=Second.to_int(secondx)letdefault_format="%T"letfrom_business___=bad_format"from_business"letday_of_week_=bad_format"day_of_week"letday_of_month_=bad_format"day_of_month"letday_of_year_=bad_format"day_of_year"letweek_=bad_format"week"letmonth_=bad_format"month"letint_month_=bad_format"int_month"letyear_=bad_format"year"letcentury_=bad_format"century"letseconds_since_1970_=bad_format"seconds_since_1970"end)modulePrecise_Calendar=Make(structincludeCalendar.Preciseletmakeymdhmns=cannot_create_event"calendar"[y;m;d;h;mn;s];makeymdhmnsletfrom_businessywd=from_date(Date.from_businessywd)letdefault_format="%i %T"letcenturyc=Date.century(yearc)letseconds_since_1970c=letp=subc(make197011000)inTime.Second.to_int(Time.Period.to_seconds(Period.to_timep))letmake=Intmakeend)moduleCalendar=Make(structincludeCalendarletmakeymdhmns=cannot_create_event"calendar"[y;m;d;h;mn;s];makeymdhmnsletfrom_businessywd=from_date(Date.from_businessywd)letdefault_format="%i %T"letcenturyc=Date.century(yearc)letseconds_since_1970c=letp=subc(make197011000)inTime.Second.to_int(Time.Period.to_seconds(Period.to_timep))letmake=Intmakeend)moduleCalendarPrinter=CalendarmodulePrecise_Fcalendar=Make(structincludeFcalendar.Preciseletmakeymdhmns=cannot_create_event"calendar"[y;m;d;h;mn;Utils.Float.rounds];makeymdhmnsletfrom_businessywd=from_date(Date.from_businessywd)letseconds=Time.Second.to_int(seconds)letdefault_format="%i %T"letcenturyc=Date.century(yearc)letseconds_since_1970c=letp=subc(make197011000.)inTime.Second.to_int(Time.Period.to_seconds(Period.to_timep))letmake=Floatmakeend)moduleFcalendar=Make(structincludeFcalendarletmakeymdhmns=cannot_create_event"calendar"[y;m;d;h;mn;Utils.Float.rounds];makeymdhmnsletfrom_businessywd=from_date(Date.from_businessywd)letseconds=Time.Second.to_int(seconds)letdefault_format="%i %T"letcenturyc=Date.century(yearc)letseconds_since_1970c=letp=subc(make197011000.)inTime.Second.to_int(Time.Period.to_seconds(Period.to_timep))letmake=Floatmakeend)