# HG changeset patch # User Adam Chlipala # Date 1392725221 18000 # Node ID abb6981a2c4c4daa36e99c74ec6385c3a1993ced # Parent 6bea98c7f7365078c1185b6d196ab0551375aed5# Parent b2254554542f848506d19ccd48567a59a84c2343 Merge with small clean-ups diff -r 6bea98c7f736 -r abb6981a2c4c Makefile.am --- a/Makefile.am Mon Feb 17 14:34:48 2014 -0500 +++ b/Makefile.am Tue Feb 18 07:07:01 2014 -0500 @@ -95,13 +95,12 @@ endif uninstall-local-main: - rm -f $(DESTDIR)$(BIN)/urweb \ - $(DESTDIR)$(LIB_UR)/basis.urs $(DESTDIR)$(LIB_UR)/char.urs $(DESTDIR)$(LIB_UR)/listPair.urs $(DESTDIR)$(LIB_UR)/list.urs \ - $(DESTDIR)$(LIB_UR)/monad.urs $(DESTDIR)$(LIB_UR)/option.urs $(DESTDIR)$(LIB_UR)/string.urs $(DESTDIR)$(LIB_UR)/top.urs \ - $(DESTDIR)$(LIB_UR)/char.ur $(DESTDIR)$(LIB_UR)/listPair.ur $(DESTDIR)$(LIB_UR)/list.ur \ - $(DESTDIR)$(LIB_UR)/monad.ur $(DESTDIR)$(LIB_UR)/option.ur $(DESTDIR)$(LIB_UR)/string.ur $(DESTDIR)$(LIB_UR)/top.ur \ - $(DESTDIR)$(LIB_JS)/urweb.js \ - $(DESTDIR)$(INCLUDE)/config.h $(DESTDIR)$(INCLUDE)/queue.h $(DESTDIR)$(INCLUDE)/request.h $(DESTDIR)$(INCLUDE)/types.h \ + rm -f $(DESTDIR)$(BIN)/urweb $(DESTDIR)$(LIB_UR)/basis.urs $(DESTDIR)$(LIB_UR)/char.urs $(DESTDIR)$(LIB_UR)/datetime.urs \ + $(DESTDIR)$(LIB_UR)/listPair.urs $(DESTDIR)$(LIB_UR)/list.urs $(DESTDIR)$(LIB_UR)/monad.urs \ + $(DESTDIR)$(LIB_UR)/option.urs $(DESTDIR)$(LIB_UR)/string.urs $(DESTDIR)$(LIB_UR)/top.urs $(DESTDIR)$(LIB_UR)/char.ur \ + $(DESTDIR)$(LIB_UR)/datetime.ur $(DESTDIR)$(LIB_UR)/listPair.ur $(DESTDIR)$(LIB_UR)/list.ur $(DESTDIR)$(LIB_UR)/monad.ur \ + $(DESTDIR)$(LIB_UR)/option.ur $(DESTDIR)$(LIB_UR)/string.ur $(DESTDIR)$(LIB_UR)/top.ur $(DESTDIR)$(LIB_JS)/urweb.js \ + $(DESTDIR)$(INCLUDE)/config.h $(DESTDIR)$(INCLUDE)/queue.h $(DESTDIR)$(INCLUDE)/request.h $(DESTDIR)$(INCLUDE)/types.h \ $(DESTDIR)$(INCLUDE)/urweb.h $(DESTDIR)$(INCLUDE)/types_cpp.h $(DESTDIR)$(INCLUDE)/urweb_cpp.h uninstall-local: uninstall-local-main uninstall-emacs diff -r 6bea98c7f736 -r abb6981a2c4c demo/more/orm1.ur --- a/demo/more/orm1.ur Mon Feb 17 14:34:48 2014 -0500 +++ b/demo/more/orm1.ur Tue Feb 18 07:07:01 2014 -0500 @@ -40,7 +40,7 @@ | Some r => {[r.B]}} ) lsS} - + fun main () = return
diff -r 6bea98c7f736 -r abb6981a2c4c include/urweb/urweb_cpp.h --- a/include/urweb/urweb_cpp.h Mon Feb 17 14:34:48 2014 -0500 +++ b/include/urweb/urweb_cpp.h Tue Feb 18 07:07:01 2014 -0500 @@ -268,6 +268,14 @@ uw_Basis_int uw_Basis_toSeconds(struct uw_context *, uw_Basis_time); uw_Basis_int uw_Basis_diffInMilliseconds(struct uw_context *, uw_Basis_time, uw_Basis_time); uw_Basis_int uw_Basis_toMilliseconds(struct uw_context *, uw_Basis_time); +uw_Basis_time uw_Basis_fromDatetime(struct uw_context *, uw_Basis_int, uw_Basis_int, uw_Basis_int, uw_Basis_int, uw_Basis_int, uw_Basis_int); +uw_Basis_int uw_Basis_datetimeYear(struct uw_context *, uw_Basis_time); +uw_Basis_int uw_Basis_datetimeMonth(struct uw_context *, uw_Basis_time); +uw_Basis_int uw_Basis_datetimeDay(struct uw_context *, uw_Basis_time); +uw_Basis_int uw_Basis_datetimeHour(struct uw_context *, uw_Basis_time); +uw_Basis_int uw_Basis_datetimeMinute(struct uw_context *, uw_Basis_time); +uw_Basis_int uw_Basis_datetimeSecond(struct uw_context *, uw_Basis_time); +uw_Basis_int uw_Basis_datetimeDayOfWeek(struct uw_context *, uw_Basis_time); extern const uw_Basis_time uw_Basis_minTime; void uw_register_transactional(struct uw_context *, void *data, uw_callback commit, uw_callback rollback, uw_callback_with_retry free); diff -r 6bea98c7f736 -r abb6981a2c4c lib/js/urweb.js --- a/lib/js/urweb.js Mon Feb 17 14:34:48 2014 -0500 +++ b/lib/js/urweb.js Tue Feb 18 07:07:01 2014 -0500 @@ -217,13 +217,13 @@ var y = d.getFullYear(); var V = parseInt(Dt.formats.V(d), 10); var W = parseInt(Dt.formats.W(d), 10); - + if(W > V) { y++; } else if(W===0 && V>=52) { y--; } - + return y; }, H: ["getHours", "0"], @@ -262,7 +262,7 @@ { idow = Dt.formats.V(new Date("" + (d.getFullYear()-1) + "/12/31")); } - + return xPad(idow, 0); }, w: "getDay", @@ -345,7 +345,39 @@ var thisDate = new Date(); thisDate.setTime(Math.floor(thisTime / 1000)); return Dt.format(thisDate, fmt); -}; +}; + +function fromDatetime(year, month, date, hour, minute, second) { + return (new Date(year, month, date, hour, minute, second)).getTime() * 1000; +}; + +function datetimeYear(t) { + return (new Date(t / 1000)).getYear() + 1900; +}; + +function datetimeMonth(t) { + return (new Date(t / 1000)).getMonth(); +}; + +function datetimeDay(t) { + return (new Date(t / 1000)).getDate(); +}; + +function datetimeHour(t) { + return (new Date(t / 1000)).getHours(); +}; + +function datetimeMinute(t) { + return (new Date(t / 1000)).getMinutes(); +}; + +function datetimeSecond(t) { + return (new Date(t / 1000)).getSeconds(); +}; + +function datetimeDayOfWeek(t) { + return (new Date(t / 1000)).getDay(); +}; // Error handling @@ -717,7 +749,7 @@ if (node.tagName == "SCRIPT") { var savedScript = thisScript; thisScript = node; - + try { eval(thisScript.text); } catch (v) { @@ -1102,7 +1134,7 @@ x.signal = s_class; x.sources = null; x.closures = htmlCls; - + x.recreate = function(v) { for (var ls = x.closures; ls != htmlCls; ls = ls.next) freeClosure(ls.data); @@ -1123,7 +1155,7 @@ x.signal = s_style; x.sources = null; x.closures = htmlCls2; - + x.recreate = function(v) { for (var ls = x.closures; ls != htmlCls2; ls = ls.next) freeClosure(ls.data); diff -r 6bea98c7f736 -r abb6981a2c4c lib/ur/basis.urs --- a/lib/ur/basis.urs Mon Feb 17 14:34:48 2014 -0500 +++ b/lib/ur/basis.urs Tue Feb 18 07:07:01 2014 -0500 @@ -167,6 +167,16 @@ val timef : string -> time -> string (* Uses strftime() format string *) val readUtc : string -> option time +(* Takes a year, month, day, hour, minute, second. *) +val fromDatetime : int -> int -> int -> int -> int -> int -> time +val datetimeYear : time -> int +val datetimeMonth : time -> int +val datetimeDay : time -> int +val datetimeHour : time -> int +val datetimeMinute: time -> int +val datetimeSecond : time -> int +val datetimeDayOfWeek : time -> int + (** * Encryption *) diff -r 6bea98c7f736 -r abb6981a2c4c lib/ur/datetime.ur --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/ur/datetime.ur Tue Feb 18 07:07:01 2014 -0500 @@ -0,0 +1,135 @@ +datatype day_of_week = Sunday | Monday | Tuesday | Wednesday | Thursday | + Friday | Saturday + +val show_day_of_week = mkShow (fn dow => case dow of + Sunday => "Sunday" + | Monday => "Monday" + | Tuesday => "Tuesday" + | Wednesday => "Wednesday" + | Thursday => "Thursday" + | Friday => "Friday" + | Saturday => "Saturday") + +fun dayOfWeekToInt dow = case dow of + Sunday => 0 + | Monday => 1 + | Tuesday => 2 + | Wednesday => 3 + | Thursday => 4 + | Friday => 5 + | Saturday => 6 + +fun intToDayOfWeek i = case i of + 0 => Sunday + | 1 => Monday + | 2 => Tuesday + | 3 => Wednesday + | 4 => Thursday + | 5 => Friday + | 6 => Saturday + | n => error Invalid day of week {[n]} + +val eq_day_of_week = mkEq (fn a b => dayOfWeekToInt a = dayOfWeekToInt b) + + +datatype month = January | February | March | April | May | June | July | + August | September | October | November | December + +val show_month = mkShow (fn m => case m of + January => "January" + | February => "February" + | March => "March" + | April => "April" + | May => "May" + | June => "June" + | July => "July" + | August => "August" + | September => "September" + | October => "October" + | November => "November" + | December => "December") + +type t = { + Year : int, + Month : month, + Day : int, + Hour : int, + Minute : int, + Second : int +} + +fun monthToInt m = case m of + January => 0 + | February => 1 + | March => 2 + | April => 3 + | May => 4 + | June => 5 + | July => 6 + | August => 7 + | September => 8 + | October => 9 + | November => 10 + | December => 11 + +fun intToMonth i = case i of + 0 => January + | 1 => February + | 2 => March + | 3 => April + | 4 => May + | 5 => June + | 6 => July + | 7 => August + | 8 => September + | 9 => October + | 10 => November + | 11 => December + | n => error Invalid month number {[n]} + +val eq_month = mkEq (fn a b => monthToInt a = monthToInt b) + + +fun toTime dt : time = fromDatetime dt.Year (monthToInt dt.Month) dt.Day + dt.Hour dt.Minute dt.Second + +fun fromTime t : t = { + Year = datetimeYear t, + Month = intToMonth (datetimeMonth t), + Day = datetimeDay t, + Hour = datetimeHour t, + Minute = datetimeMinute t, + Second = datetimeSecond t +} + +val ord_datetime = mkOrd { Lt = fn a b => toTime a < toTime b, + Le = fn a b => toTime a <= toTime b } + +fun format fmt dt : string = timef fmt (toTime dt) + +fun dayOfWeek dt : day_of_week = intToDayOfWeek (datetimeDayOfWeek (toTime dt)) + +val now : transaction t = + n <- now; + return (fromTime n) + +(* Normalize a datetime. This will convert, e.g., January 32nd into February + 1st. *) + +fun normalize dt = fromTime (toTime dt) +fun addToField [nm :: Name] [rest ::: {Type}] [[nm] ~ rest] + (delta : int) (r : $([nm = int] ++ rest)) + : $([nm = int] ++ rest) = + (r -- nm) ++ {nm = r.nm + delta} + + +(* Functions for adding to a datetime. There is no addMonths or addYears since + it's not clear what should be done; what's 1 month after January 31, or 1 + year after February 29th? + + These can't all be defined in terms of addSeconds because of leap seconds. *) + +fun addSeconds n dt = normalize (addToField [#Second] n dt) +fun addMinutes n dt = normalize (addToField [#Minute] n dt) +fun addHours n dt = normalize (addToField [#Hour] n dt) +fun addDays n dt = normalize (addToField [#Day] n dt) diff -r 6bea98c7f736 -r abb6981a2c4c lib/ur/datetime.urs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/ur/datetime.urs Tue Feb 18 07:07:01 2014 -0500 @@ -0,0 +1,38 @@ +datatype day_of_week = Sunday | Monday | Tuesday | Wednesday | Thursday | + Friday | Saturday + +datatype month = January | February | March | April | May | June | July | + August | September | October | November | December + + +type t = { + Year : int, + Month : month, + Day : int, + Hour : int, + Minute : int, + Second : int +} + +val ord_datetime : ord t + +val show_day_of_week : show day_of_week +val show_month : show month +val eq_day_of_week : eq day_of_week +val eq_month : eq month +val dayOfWeekToInt : day_of_week -> int +val intToDayOfWeek : int -> day_of_week +val monthToInt : month -> int +val intToMonth : int -> month + +val toTime : t -> time +val fromTime : time -> t +val format : string -> t -> string +val dayOfWeek : t -> day_of_week +val now : transaction t +val normalize : t -> t + +val addSeconds : int -> t -> t +val addMinutes : int -> t -> t +val addHours : int -> t -> t +val addDays : int -> t -> t diff -r 6bea98c7f736 -r abb6981a2c4c src/c/urweb.c --- a/src/c/urweb.c Mon Feb 17 14:34:48 2014 -0500 +++ b/src/c/urweb.c Tue Feb 18 07:07:01 2014 -0500 @@ -847,7 +847,7 @@ break; default: break; - } + } } size_t uw_subinputs_max = SIZE_MAX; @@ -1863,12 +1863,12 @@ uw_unit uw_Basis_urlifyChannel_w(uw_context ctx, uw_Basis_channel chn) { if (ctx->client != NULL && chn.cli == ctx->client->id) { int len; - + uw_check(ctx, INTS_MAX + 1); sprintf(ctx->page.front, "%u%n", chn.chn, &len); ctx->page.front += len; } - + return uw_unit_v; } @@ -1929,11 +1929,11 @@ uw_unit uw_Basis_urlifySource_w(uw_context ctx, uw_Basis_source src) { int len; - + uw_check(ctx, 2 * INTS_MAX + 2); sprintf(ctx->page.front, "%d/%llu%n", src.context, src.source, &len); ctx->page.front += len; - + return uw_unit_v; } @@ -2024,7 +2024,7 @@ uw_Basis_bool uw_Basis_unurlifyBool(uw_context ctx, char **s) { char *new_s = uw_unurlify_advance(*s); uw_Basis_bool r; - + if (*s[0] == 0 || !strcmp(*s, "0") || !strcmp(*s, "off")) r = uw_Basis_False; else @@ -2085,7 +2085,7 @@ uw_check(ctx, INTS_MAX); sprintf(ctx->page.front, "%lld%n", n, &len); ctx->page.front += len; - + return uw_unit_v; } @@ -2149,7 +2149,7 @@ uw_check(ctx, INTS_MAX); sprintf(ctx->page.front, "%lld%n", (uw_Basis_int)n, &len); ctx->page.front += len; - + return uw_unit_v; } @@ -2253,7 +2253,7 @@ uw_check(ctx, 2 * INTS_MAX + 1); sprintf(ctx->page.front, "s%d_%llu%n", src.context, src.source, &len); ctx->page.front += len; - + return uw_unit_v; } @@ -2363,7 +2363,7 @@ r[len] = 0; return r; } - + } uw_Basis_string uw_Basis_str1(uw_context ctx, uw_Basis_char ch) { @@ -2587,7 +2587,7 @@ sprintf(s2, "%02X", c); s2 += 2; } - } + } *s2++ = '\''; strcpy(s2, uw_sqlsuffixBlob); @@ -3254,7 +3254,7 @@ if (!s || strlen(haystack) - (s - haystack) - (sizeof sig_intro - 1) < uw_hash_blocksize*2+1) return NULL; - + s += sizeof sig_intro - 1; for (i = 0; i < uw_hash_blocksize*2; ++i) @@ -3667,7 +3667,7 @@ uw_Basis_string uw_Basis_makeSigString(uw_context ctx, uw_Basis_string sig) { uw_Basis_string r = uw_malloc(ctx, 2 * uw_hash_blocksize + 1); int i; - + for (i = 0; i < uw_hash_blocksize; ++i) sprintf(&r[2*i], "%.02X", ((unsigned char *)sig)[i]); @@ -3885,7 +3885,7 @@ va_list ap; size_t len = 1; char *s, *r, *s2; - + va_start(ap, ctx); for (s = va_arg(ap, char*); s; s = va_arg(ap, char*)) len += strlen(s); @@ -3930,6 +3930,56 @@ return tm.seconds; } +uw_Basis_time uw_Basis_fromDatetime(uw_context ctx, uw_Basis_int year, uw_Basis_int month, uw_Basis_int day, uw_Basis_int hour, uw_Basis_int minute, uw_Basis_int second) { + struct tm tm = { .tm_year = year - 1900, .tm_mon = month, .tm_mday = day, + .tm_hour = hour, .tm_min = minute, .tm_sec = second }; + uw_Basis_time r = { timelocal(&tm) }; + return r; +} + +uw_Basis_int uw_Basis_datetimeYear(uw_context ctx, uw_Basis_time time) { + struct tm tm; + localtime_r(&time.seconds, &tm); + return tm.tm_year + 1900; +} + +uw_Basis_int uw_Basis_datetimeMonth(uw_context ctx, uw_Basis_time time) { + struct tm tm; + localtime_r(&time.seconds, &tm); + return tm.tm_mon; +} + +uw_Basis_int uw_Basis_datetimeDay(uw_context ctx, uw_Basis_time time) { + struct tm tm; + localtime_r(&time.seconds, &tm); + return tm.tm_mday; +} + +uw_Basis_int uw_Basis_datetimeHour(uw_context ctx, uw_Basis_time time) { + struct tm tm; + localtime_r(&time.seconds, &tm); + return tm.tm_hour; +} + +uw_Basis_int uw_Basis_datetimeMinute(uw_context ctx, uw_Basis_time time) { + struct tm tm; + localtime_r(&time.seconds, &tm); + return tm.tm_min; +} + +uw_Basis_int uw_Basis_datetimeSecond(uw_context ctx, uw_Basis_time time) { + struct tm tm; + localtime_r(&time.seconds, &tm); + return tm.tm_sec; +} + +uw_Basis_int uw_Basis_datetimeDayOfWeek(uw_context ctx, uw_Basis_time time) { + struct tm tm; + localtime_r(&time.seconds, &tm); + return tm.tm_wday; +} + + void *uw_get_global(uw_context ctx, char *name) { int i; @@ -4067,7 +4117,7 @@ pthread_mutex_lock(&rand_mutex); int r = RAND_bytes((unsigned char *)&ret, sizeof ret); pthread_mutex_unlock(&rand_mutex); - + if (r) return abs(ret); else diff -r 6bea98c7f736 -r abb6981a2c4c src/settings.sml --- a/src/settings.sml Mon Feb 17 14:34:48 2014 -0500 +++ b/src/settings.sml Tue Feb 18 07:07:01 2014 -0500 @@ -331,6 +331,16 @@ ("toMilliseconds", "toMilliseconds"), ("diffInMilliseconds", "diffInMilliseconds"), + ("fromDatetime", "fromDatetime"), + ("datetimeYear", "datetimeYear"), + ("datetimeMonth", "datetimeMonth"), + ("datetimeDay", "datetimeDay"), + ("datetimeHour", "datetimeHour"), + ("datetimeMinute", "datetimeMinute"), + ("datetimeSecond", "datetimeSecond"), + ("datetimeDayOfWeek", "datetimeDayOfWeek"), + + ("onClick", "uw_onClick"), ("onDblclick", "uw_onDblclick"), ("onKeydown", "uw_onKeydown"),