Permalink
Browse files

[enhance] stdlib: Add %z (timezone) handling in Date code.

This diff does not add total timezone handling (i.e. it doesn't allow you to parse the timezone from a string and/or mess around with timezone values). The main purpose of this diff is to have the ability to tell which timezone the server or client is running in, which is sometimes useful.
  • Loading branch information...
1 parent ae141ca commit 11a55a7a1f36ca2e54c7cb1e2c172b4c80ff3325 Alok Menghrajani committed with BourgerieQuentin Feb 4, 2012
Showing with 49 additions and 2 deletions.
  1. +8 −0 libbase/time.ml
  2. +1 −0 libbase/time.mli
  3. +7 −0 opabsl/jsbsl/bslTime.js
  4. +3 −0 opabsl/mlbsl/bslTime.ml
  5. +25 −2 stdlib/core/date/date.opa
  6. +5 −0 stdlib/core/date/date_private.opa
View
@@ -105,6 +105,14 @@ let local_wday time = (localtime time).Unix.tm_wday
let local_yday time = (localtime time).Unix.tm_yday
let local_isdst time = (localtime time).Unix.tm_isdst
+let local_timezone_offset () =
+ let t = Unix.time() in
+ let gmt = Unix.gmtime(t) in
+ let local = Unix.localtime(t) in
+ let (gmt_s, _) = Unix.mktime(gmt) in
+ let (local_s, _) = Unix.mktime(local) in
+ int_of_float((gmt_s -. local_s) /. 60.0);;
+
let mktime ~year ~month ~day ~h ~min ~sec ~ms =
let res =
of_unix_time (
View
@@ -52,6 +52,7 @@ val local_year : t -> int
val local_wday : t -> int
val local_yday : t -> int
val local_isdst : t -> bool
+val local_timezone_offset : unit -> int
val mktime : year:int -> month:int -> day:int -> h:int -> min:int -> sec:int -> ms:int -> t
View
@@ -159,6 +159,13 @@ function now()
return t.getHours();
}
+##register local_timezone_offset : time_t -> int
+ ##args(f)
+{
+ var t = new Date(); t.setTime(f)
+ return t.getTimezoneOffset();
+}
+
##register local_mday : time_t -> int
##args(f)
{
View
@@ -83,6 +83,9 @@
##register local_hour : time_t -> int
let local_hour t = Time.local_hour (wrap t)
+ ##register local_timezone_offset : time_t -> int
+ let local_timezone_offset _ = Time.local_timezone_offset()
+
##register local_mday : time_t -> int
let local_mday t = Time.local_mday (wrap t)
View
@@ -424,6 +424,29 @@ type time_t = external
get_hour : Date.date -> int = Date_private.time_local_hour
/**
+ * Returns the local timezone (+hhmm or -hhmm).
+ *
+ * On the server side, this will be a constant. On the client side
+ * it will depend on whatever the user has set on their system.
+ *
+ * @return The local timezone (+hhmm or -hhmm).
+ **/
+ get_local_timezone : -> string = -> (
+ t : Date.date = Date.now()
+ delta : int = Date_private.time_local_timezone_offset(t)
+ // delta is the timezone in minutes, so we need to convert it into
+ // +hhmm or -hhmm. If delta is positive, the timezone is -hhmm. Otherwise
+ // the timezone is +hhmm.
+ h : int = Int.abs(delta) / 60
+ m : int = mod(Int.abs(delta), 60)
+ s : string = if delta > 0 then "-" else "+"
+ p = {pad_with_zeros}
+ h_str : string = Date_private.ToString.pad(h, p, p, 2)
+ m_str : string = Date_private.ToString.pad(m, p, p, 2)
+ "{s}{h_str}{m_str}"
+ )
+
+ /**
* Returns the weekday represented by this date interpreted in the local
* time zone.
* If you need to completely decompose a date consider using {!Date.to_human_readable}.
@@ -833,6 +856,7 @@ type time_t = external
* - [%w] day of week (0..6); 0 is Sunday
* - [%y] last two digits of year (00..99)
* - [%Y] year (ex. 2010)
+ * - [%z] +hhmm numeric timezone (e.g., -0400)
*
* By default, numeric fields are padded with zeroes. The following optional flags
* may follow `%':
@@ -849,7 +873,6 @@ type time_t = external
* - [%U] week number of year with Sunday as first day of week (00..53)
* - [%V] week number of year with Monday as first day of week (01..53)
* - [%W] week number of year with Monday as first day of week (00..53)
- * - [%z] +hhmm numeric timezone (e.g., -0400)
* - [%:z] +hh:mm numeric timezone (e.g., -04:00)
*
* Also the padding directives are not supported:
@@ -975,7 +998,7 @@ type time_t = external
*
* For the purpose of parsing there are few differences in the interpretations
* of the format, compared to the format used for printing, see {!Date.try_generate_printer}:
- * - the directives '%C', '%u' and '%w' are not recognized,
+ * - the directives '%C', '%u', '%w' and '%z' are not recognized,
* - a non-empty sequence of spaces in the [format] can be matched by any (non-empty)
* sequence of spaces in the input.
* - the padding flags ('_', '-' and '0') are ignored and all numerical values
@@ -105,6 +105,9 @@ import stdlib.core.parser
time_local_hour : Date.date -> int =
date_in(%%BslTime.local_hour%% : time_t -> int) // Hours 0..23
+ time_local_timezone_offset : Date.date -> int =
+ date_in(%%BslTime.local_timezone_offset%% : time_t -> int)
+
time_local_mday : Date.date -> int =
date_in(%%BslTime.local_mday%% : time_t -> int) // Day of month 1..31
@@ -181,6 +184,7 @@ import stdlib.core.parser
, ("x", true, ((p, d) -> pad(Date.get_msec(d), p, {pad_with_zeros}, 3)))
, ("y", false, ((_, d) -> pad(mod(Date.get_year(d), 100), {pad_with_zeros}, {pad_with_zeros}, 2)))
, ("Y", true, ((p, d) -> pad(Date.get_year(d), p, {pad_with_spaces}, 4)))
+ , ("z", true, ((_, _) -> Date.get_local_timezone()))
]
padding_flag_parser = parser
@@ -328,6 +332,7 @@ import stdlib.core.parser
, ("x", parse_num(v -> d -> {d with ms = v}))
, ("y", parse_num(v -> d -> {d with year=if v < 70 then 2000 + v else 1900 + v}))
, ("Y", parse_num(v -> d -> {d with year=v}))
+// , ("z", *not supported for parsing*
]
parse_directive_with((d, p)) =

0 comments on commit 11a55a7

Please sign in to comment.