From 1f8c95ba28a59bf8459a15c8b2d52234e577e191 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 14:56:13 -0400 Subject: [PATCH 01/16] luatz/timetable: Optimize and export `is_leap`; add tests --- luatz/timetable.lua | 9 ++++++++- spec/timetable_spec.lua | 13 +++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/luatz/timetable.lua b/luatz/timetable.lua index f096372..99ac52e 100644 --- a/luatz/timetable.lua +++ b/luatz/timetable.lua @@ -16,7 +16,13 @@ end local sakamoto = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; local function is_leap ( y ) - return (y % 4) == 0 and (y % 100) ~= 0 or (y % 400) == 0 + if (y % 4) ~= 0 then + return false + elseif (y % 100) ~= 0 then + return true + else + return (y % 400) == 0 + end end local function year_length ( y ) @@ -200,6 +206,7 @@ local function new_from_timestamp ( ts ) end return { + is_leap = is_leap ; day_of_year = day_of_year ; day_of_week = day_of_week ; normalise = normalise ; diff --git a/spec/timetable_spec.lua b/spec/timetable_spec.lua index b769911..0ff42b1 100644 --- a/spec/timetable_spec.lua +++ b/spec/timetable_spec.lua @@ -9,6 +9,19 @@ describe ( "Timetable library" , function ( ) }) end + it ( "#is_leap is correct" , function ( ) + assert.same ( false , timetable.is_leap ( 1 ) ) + assert.same ( false , timetable.is_leap ( 3 ) ) + assert.same ( true , timetable.is_leap ( 4 ) ) + assert.same ( true , timetable.is_leap ( 2000 ) ) + assert.same ( true , timetable.is_leap ( 2004 ) ) + assert.same ( true , timetable.is_leap ( 2012 ) ) + assert.same ( false , timetable.is_leap ( 2013 ) ) + assert.same ( false , timetable.is_leap ( 2014 ) ) + assert.same ( false , timetable.is_leap ( 2100 ) ) + assert.same ( true , timetable.is_leap ( 2400 ) ) + end ) + it ( "#normalise gets #wday (day of week) correct" , function ( ) local function assert_same_wday ( year , month , day ) -- 2.39.5 From 32aa8ae47d86e8321ca8b00df394eaeccd160b21 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 15:02:52 -0400 Subject: [PATCH 02/16] luatz/timetable: Rename `increment` to `carry` --- luatz/timetable.lua | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/luatz/timetable.lua b/luatz/timetable.lua index 99ac52e..879f0a2 100644 --- a/luatz/timetable.lua +++ b/luatz/timetable.lua @@ -56,7 +56,7 @@ local function day_of_week ( day , month , year ) return ( year + leap_years_since ( year ) + sakamoto[month] + day ) % 7 + 1 end -local function increment ( tens , units , base ) +local function carry ( tens , units , base ) if units >= base then tens = tens + idiv ( units , base ) units = units % base @@ -69,9 +69,11 @@ end -- Modify parameters so they all fit within the "normal" range local function normalise ( year , month , day , hour , min , sec ) - min , sec = increment ( min , sec , 60 ) -- TODO: consider leap seconds? - hour , min = increment ( hour , min , 60 ) - day , hour = increment ( day , hour , 24 ) + -- Propagate out of range values up + -- e.g. if `min` is 70, `hour` increments by 1 and `min` becomes 10 + min , sec = carry ( min , sec , 60 ) -- TODO: consider leap seconds? + hour , min = carry ( hour , min , 60 ) + day , hour = carry ( day , hour , 24 ) while day <= 0 do year = year - 1 @@ -80,7 +82,7 @@ local function normalise ( year , month , day , hour , min , sec ) -- Lua months start from 1, need -1 and +1 around this increment month = month - 1 - year , month = increment ( year , month , 12 ) + year , month = carry ( year , month , 12 ) month = month + 1 -- This could potentially be slow if `day` is very large -- 2.39.5 From 6ba1e0b1252c68552bf5aa841a95f63eb04b7050 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 16:02:40 -0400 Subject: [PATCH 03/16] spec/timetable_spec: more tests --- spec/timetable_spec.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/spec/timetable_spec.lua b/spec/timetable_spec.lua index 0ff42b1..34c0529 100644 --- a/spec/timetable_spec.lua +++ b/spec/timetable_spec.lua @@ -41,6 +41,8 @@ describe ( "Timetable library" , function ( ) assert_same_wday ( 2014 , 1 , 1 ) assert_same_wday ( 2014 , 1 , 6 ) assert_same_wday ( 2016 , 2 , 28 ) + assert_same_wday ( 2016 , 2 , 29 ) + assert_same_wday ( 2016 , 3 , 1 ) end ) local function native_timestamp ( year , month , day ) @@ -57,6 +59,16 @@ describe ( "Timetable library" , function ( ) end end ) + it ( "#normalise handles out of range days in a year" , function ( ) + assert.same ( { timetable.normalise(2013,1,366,0,0,0) } , { 2014,1,1,0,0,0 } ) + assert.same ( { timetable.normalise(2013,1,400,0,0,0) } , { 2014,2,4,0,0,0 } ) + assert.same ( { timetable.normalise(2016,1,400,0,0,0) } , { 2017,2,3,0,0,0 } ) + assert.same ( { timetable.normalise(2015,1,430,0,0,0) } , { 2016,3,5,0,0,0 } ) + assert.same ( { timetable.normalise(2016,1,430,0,0,0) } , { 2017,3,5,0,0,0 } ) + assert.same ( { timetable.normalise(2000,1,10000,0,0,0) } , { 2027,5,18,0,0,0 } ) + assert.same ( { timetable.normalise(2000,1,10000000,0,0,0) } , { 29379,1,25,0,0,0 } ) + end ) + it ( "#normalise handles out of range days in a #month" , function ( ) assert.same ( { timetable.normalise(2013,0,1,0,0,0) } , { 2012,12,1,0,0,0 } ) assert.same ( { timetable.normalise(2013,42,1,0,0,0) } , { 2016,6,1,0,0,0 } ) -- 2.39.5 From 6c4658848c01ae0862a2fcad7f6565efd9aa948d Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 16:03:47 -0400 Subject: [PATCH 04/16] luatz/timetable: Add support to `normalise` for fractional columns --- luatz/timetable.lua | 45 +++++++++++++++++++++++++++++++---------- spec/timetable_spec.lua | 20 ++++++++++++++++++ 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/luatz/timetable.lua b/luatz/timetable.lua index 879f0a2..3e80242 100644 --- a/luatz/timetable.lua +++ b/luatz/timetable.lua @@ -56,6 +56,13 @@ local function day_of_week ( day , month , year ) return ( year + leap_years_since ( year ) + sakamoto[month] + day ) % 7 + 1 end +local function borrow ( tens , units , base ) + local frac = tens % 1 + units = units + frac * base + tens = tens - frac + return tens , units +end + local function carry ( tens , units , base ) if units >= base then tens = tens + idiv ( units , base ) @@ -69,34 +76,50 @@ end -- Modify parameters so they all fit within the "normal" range local function normalise ( year , month , day , hour , min , sec ) + -- `month` and `day` start from 1, need -1 and +1 so it works modulo + month , day = month - 1 , day - 1 + + -- Convert everything (except seconds) to an integer + -- by propagating fractional components down. + year , month = borrow ( year , month , 12 ) + -- Carry from month to year first, so we get month length correct in next line around leap years + year , month = carry ( year , month , 12 ) + month , day = borrow ( month , day , month_length ( floor ( month + 1 ) , year ) ) + day , hour = borrow ( day , hour , 24 ) + hour , min = borrow ( hour , min , 60 ) + min , sec = borrow ( min , sec , 60 ) + -- Propagate out of range values up -- e.g. if `min` is 70, `hour` increments by 1 and `min` becomes 10 + -- This has to happen for all columns after borrowing, as lower radixes may be pushed out of range min , sec = carry ( min , sec , 60 ) -- TODO: consider leap seconds? hour , min = carry ( hour , min , 60 ) day , hour = carry ( day , hour , 24 ) - - while day <= 0 do + -- Ensure `day` is not underflowed + -- Add a whole year of days at a time, this is later resolved by adding months + -- TODO[OPTIMIZE]: This could be slow if `day` is far out of range + while day < 0 do year = year - 1 day = day + year_length ( year ) end - - -- Lua months start from 1, need -1 and +1 around this increment - month = month - 1 year , month = carry ( year , month , 12 ) - month = month + 1 - -- This could potentially be slow if `day` is very large + -- TODO[OPTIMIZE]: This could potentially be slow if `day` is very large while true do - local i = month_length ( month , year ) - if day <= i then break end + local i = month_length ( month + 1 , year ) + if day < i then break end day = day - i month = month + 1 - if month > 12 then - month = 1 + if month >= 12 then + month = 0 year = year + 1 end end + -- Now we can place `day` and `month` back in their normal ranges + -- e.g. month as 1-12 instead of 0-11 + month , day = month + 1 , day + 1 + return year , month , day , hour , min , sec end diff --git a/spec/timetable_spec.lua b/spec/timetable_spec.lua index 34c0529..569864f 100644 --- a/spec/timetable_spec.lua +++ b/spec/timetable_spec.lua @@ -84,4 +84,24 @@ describe ( "Timetable library" , function ( ) assert.same ( { timetable.normalise(2013,42,52,0,0,0) } , { 2016,7,22,0,0,0 } ) assert.same ( { timetable.normalise(2013,42,52,50,0,0) } , { 2016,7,24,2,0,0 } ) end ) + + it ( "#normalise handles fractional #month" , function ( ) + assert.same ( { timetable.normalise(2014,14.5,1,0,0,0) } , { 2015,2,15,0,0,0 } ) + assert.same ( { timetable.normalise(2015,14.5,1,0,0,0) } , { 2016,2,15,12,0,0 } ) -- leap year, so hours is 12 + assert.same ( { timetable.normalise(2016,14.5,1,0,0,0) } , { 2017,2,15,0,0,0 } ) + end ) + + local function round_trip_add(t, field, x) + local before = t:clone() + t[field]=t[field]+x; + t:normalise(); + t[field]=t[field]-x; + t:normalise(); + assert.same(0, t-before) + end + it ( "#normalise round trips" , function ( ) + round_trip_add(timetable.new(2000,2,28,0,0,0), "month", 0.5) + round_trip_add(timetable.new(2014,8,28,19,23,0), "month", 0.4) + round_trip_add(timetable.new(2014,14.5,28,0,0,0), "month", 0.4) + end ) end ) -- 2.39.5 From 0c40603e021b01bd61e4297dcdda6ab3eb8839d9 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 16:34:33 -0400 Subject: [PATCH 05/16] doc/timetable: spell check --- doc/timetable.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/timetable.md b/doc/timetable.md index 86ce2b2..e3601a4 100644 --- a/doc/timetable.md +++ b/doc/timetable.md @@ -15,7 +15,7 @@ The fields are intentionally compatible with the lua standard library's `os.date - `wday` (optional) timetable components may be outside of their standard range (e.g. a month component of -14) to faciliate arithmetic operations on date components. `:normalise ( )` can be +14) to facilitate arithmetic operations on date components. `:normalise ( )` can be called to modify components to return to their standard range. Equality and comparisons should work between timetable objects. @@ -37,7 +37,7 @@ date. ## `:clone ( )` -Returns a new independant instance of an existing timetable object. +Returns a new independent instance of an existing timetable object. ## `:normalise ( )` @@ -50,14 +50,13 @@ ranges e.g. `month` is `1`-`12`; `min` is `0`-`59` Returns the timetable formatted as an rfc-3339 style string. The timezone offset (or Z) is not appended. -The ranges of components are not checked, and if you want a valid timestamp, `:normalise -( )` should be called first. +The ranges of components are not checked, if you want a valid timestamp, +`:normalise ( )` should be called first. ## `:timestamp ( )` -Returns the timetable as the number of seconds since unix epoch (1970-01-01) as a lua -number. +Returns the timetable as the number of seconds since unix epoch (1970-01-01) as a lua number. ## `:unpack ( )` -- 2.39.5 From 94c5a08ebdc03125f84e7fed814a1599c788a09e Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 16:36:10 -0400 Subject: [PATCH 06/16] Breaking change: Normalise inside of `new_from_timestamp()` --- doc/timetable.md | 5 +---- examples/date_arithmetic.lua | 2 +- examples/os_date.lua | 2 +- luatz/init.lua | 2 +- luatz/timetable.lua | 2 +- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/doc/timetable.md b/doc/timetable.md index e3601a4..92c4302 100644 --- a/doc/timetable.md +++ b/doc/timetable.md @@ -28,12 +28,9 @@ Returns a new timetable with the given contents. ## `new_from_timestamp ( timestamp )` -Returns a new timetable given a timestamp in seconds since the unix epoch of +Returns a new (normalised) timetable, given a timestamp in seconds since the unix epoch of 1970-01-01. -`:normalise ( )` should probably be called before use to resolve to the current time and -date. - ## `:clone ( )` diff --git a/examples/date_arithmetic.lua b/examples/date_arithmetic.lua index 3b1126d..d5bd92b 100644 --- a/examples/date_arithmetic.lua +++ b/examples/date_arithmetic.lua @@ -2,7 +2,7 @@ local luatz = require "luatz" -- We do this a few times ==> Convert a timestamp to timetable and normalise local function ts2tt ( ts ) - return luatz.timetable.new_from_timestamp ( ts ):normalise ( ) + return luatz.timetable.new_from_timestamp ( ts ) end -- Get the current time in UTC diff --git a/examples/os_date.lua b/examples/os_date.lua index 0164780..deac08b 100644 --- a/examples/os_date.lua +++ b/examples/os_date.lua @@ -14,7 +14,7 @@ local function os_date ( format_string , timestamp ) else -- Localtime timestamp = get_tz ( ):localise ( timestamp ) end - local tt = new_from_timestamp ( timestamp ):normalise ( ) + local tt = new_from_timestamp ( timestamp ) if format_string == "*t" then return tt else diff --git a/luatz/init.lua b/luatz/init.lua index 8ab7cfc..923e4d6 100644 --- a/luatz/init.lua +++ b/luatz/init.lua @@ -20,7 +20,7 @@ end --- C-like functions _M.gmtime = function ( ts ) - return _M.timetable.new_from_timestamp ( ts ):normalise ( ) + return _M.timetable.new_from_timestamp ( ts ) end _M.localtime = function ( ts ) diff --git a/luatz/timetable.lua b/luatz/timetable.lua index 3e80242..fc89fca 100644 --- a/luatz/timetable.lua +++ b/luatz/timetable.lua @@ -227,7 +227,7 @@ local function new_from_timestamp ( ts ) if type ( ts ) ~= "number" then error ( "bad argument #1 to 'new_from_timestamp' (number expected, got " .. type ( ts ) .. ")" , 2 ) end - return new_timetable ( 1970 , 1 , 1 , 0 , 0 , ts ) + return new_timetable ( 1970 , 1 , 1 , 0 , 0 , ts ):normalise ( ) end return { -- 2.39.5 From 8f5786554f58cae293237590d9fe918158b61561 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 16:42:58 -0400 Subject: [PATCH 07/16] doc/: Reduce functions to a h3 instead of h2 --- doc/gettime.md | 6 +++--- doc/index.md | 6 +++--- doc/parse.md | 2 +- doc/timetable.md | 14 +++++++------- doc/tzinfo.md | 6 +++--- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/doc/gettime.md b/doc/gettime.md index 2e3ef35..faabfb4 100644 --- a/doc/gettime.md +++ b/doc/gettime.md @@ -10,14 +10,14 @@ Uses the most precise method available (in order:) - [luasocket](http://w3.impa.br/~diego/software/luasocket/)'s `socket.gettime` - [`os.time`](http://www.lua.org/manual/5.2/manual.html#pdf-os.time) -## `source` +### `source` The library/function currently in use. -## `resolution` +### `resolution` The smallest time resolution (in seconds) available from `gettime ( )` . -## `gettime ( )` +### `gettime ( )` Returns the number of seconds since unix epoch (1970-01-01T00:00:00Z) as a lua number diff --git a/doc/index.md b/doc/index.md index 09e7d7d..85cf5ab 100644 --- a/doc/index.md +++ b/doc/index.md @@ -8,13 +8,13 @@ The table includes the following sub modules, which have their own documentation - `timetable`: Class for date/time objects supporting normalisation -## `time ( )` +### `time ( )` Returns the current unix timestamp using the most precise source available. See `gettime` for more information. -## `get_tz ( [timezone_name] )` +### `get_tz ( [timezone_name] )` Returns a timezone object (see `tzinfo` documentation) for the given `timezone_name`. If `timezone_name` is `nil` then the local timezone is used. @@ -25,7 +25,7 @@ names are usually of the form `Country/Largest_City` e.g. "America/New_York". Check [wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for an example list. -## `time_in ( timezone_name [, utc_ts] )` +### `time_in ( timezone_name [, utc_ts] )` Returns the current time in seconds since 1970-01-01 0:00:00 in the given timezone as a string, (same semantics as `get_tz`) at the given UTC time (defaults to now). diff --git a/doc/parse.md b/doc/parse.md index 6d72fdf..39529dd 100644 --- a/doc/parse.md +++ b/doc/parse.md @@ -4,6 +4,6 @@ Provides parsers for common time and date formats. Functions take the source string and an optional initial postition. -## `rfc_3339 ( string [, init] )` +### `rfc_3339 ( string [, init] )` Returns a luatz timetable and the (optional) time zone offset in seconds diff --git a/doc/timetable.md b/doc/timetable.md index 92c4302..845c787 100644 --- a/doc/timetable.md +++ b/doc/timetable.md @@ -21,29 +21,29 @@ called to modify components to return to their standard range. Equality and comparisons should work between timetable objects. -## `new ( year , month , day , hour , min , sec , [yday] , [wday] )` +### `new ( year , month , day , hour , min , sec , [yday] , [wday] )` Returns a new timetable with the given contents. -## `new_from_timestamp ( timestamp )` +### `new_from_timestamp ( timestamp )` Returns a new (normalised) timetable, given a timestamp in seconds since the unix epoch of 1970-01-01. -## `:clone ( )` +### `:clone ( )` Returns a new independent instance of an existing timetable object. -## `:normalise ( )` +### `:normalise ( )` Mutates the current object's time and date components so that they lie within 'normal' ranges e.g. `month` is `1`-`12`; `min` is `0`-`59` -## `:rfc_3339 ( )` and `__tostring` metamethod +### `:rfc_3339 ( )` and `__tostring` metamethod Returns the timetable formatted as an rfc-3339 style string. The timezone offset (or Z) is not appended. @@ -51,11 +51,11 @@ The ranges of components are not checked, if you want a valid timestamp, `:normalise ( )` should be called first. -## `:timestamp ( )` +### `:timestamp ( )` Returns the timetable as the number of seconds since unix epoch (1970-01-01) as a lua number. -## `:unpack ( )` +### `:unpack ( )` Unpacks the timetable object; returns `year`, `month`, `day`, `hour`, `min`, `sec`, `yday`, `wday` diff --git a/doc/tzinfo.md b/doc/tzinfo.md index 78d0453..8f95b5d 100644 --- a/doc/tzinfo.md +++ b/doc/tzinfo.md @@ -26,18 +26,18 @@ and contains the following fields: - `isgmt` (boolean) -## `:find_current ( utc_ts )` +### `:find_current ( utc_ts )` Returns the relevant `tt_info` object for the given UTC timestamp in the timezone. -## `:localise ( utc_ts )` and `:localize ( utc_ts )` +### `:localise ( utc_ts )` and `:localize ( utc_ts )` Convert the given UTC timestamp to the timezone. Returns the number of seconds since unix epoch in the given timezone. -## `:utctime ( local_ts )` +### `:utctime ( local_ts )` Convert the given local timestamp (seconds since unix epoch in the time zone) to a UTC timestamp. This may result in ambigous results, in which case multiple values are returned. -- 2.39.5 From 4c342db811aa99e6438e6dd9dff4498e1dcbd87c Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 16:44:24 -0400 Subject: [PATCH 08/16] doc/index: Add C-like functions --- doc/index.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/index.md b/doc/index.md index 85cf5ab..2b7872d 100644 --- a/doc/index.md +++ b/doc/index.md @@ -29,3 +29,13 @@ Check [wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) Returns the current time in seconds since 1970-01-01 0:00:00 in the given timezone as a string, (same semantics as `get_tz`) at the given UTC time (defaults to now). + + +## As in the C standard library + +### `gmtime ( ts )` + +### `localtime ( ts )` + +### `ctime ( ts )` + -- 2.39.5 From 1d9261eb093db6618ae886483bdde36d701289de Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 16:51:29 -0400 Subject: [PATCH 09/16] README: Add Installation instructions --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 7fa15ab..620807c 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,13 @@ Importantly, it allows you to convert time between locations (time zones). Documentation can be found in the `doc` sub-directory. [![Build Status](https://travis-ci.org/daurnimator/luatz.png)](https://travis-ci.org/daurnimator/luatz) + + +## Installation + +### via [luarocks](http://luarocks.org/) + + luarocks install luatz + +[MoonRocks link](https://rocks.moonscript.org/modules/daurnimator/luatz) + -- 2.39.5 From 98480fae7ef1afd7925d4f1d45fdefa5f3a7e475 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 16:53:43 -0400 Subject: [PATCH 10/16] README: Add feature list, Usage section --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 620807c..6a4c5cd 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,19 @@ This is a lua library for time and date manipulation. -Importantly, it allows you to convert time between locations (time zones). +Features include: + - Normalisation of broken down date objects + - Conversion between locations (time zones) using your local [zoneinfo](https://www.iana.org/time-zones) database. + - `stftime` formatting -Documentation can be found in the `doc` sub-directory. [![Build Status](https://travis-ci.org/daurnimator/luatz.png)](https://travis-ci.org/daurnimator/luatz) +## Usage + +Documentation can be found in the `doc` sub-directory. + + ## Installation ### via [luarocks](http://luarocks.org/) -- 2.39.5 From 559b74f2263f649dab60af846949536cbbb4b10c Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 16:57:26 -0400 Subject: [PATCH 11/16] luatz/init: Add `now()` function --- doc/index.md | 5 +++++ luatz/init.lua | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/doc/index.md b/doc/index.md index 2b7872d..e0ece6a 100644 --- a/doc/index.md +++ b/doc/index.md @@ -13,6 +13,11 @@ The table includes the following sub modules, which have their own documentation Returns the current unix timestamp using the most precise source available. See `gettime` for more information. +### `now ( )` + +Returns the current time as a timetable object +See `timetable` for more information + ### `get_tz ( [timezone_name] )` diff --git a/luatz/init.lua b/luatz/init.lua index 923e4d6..1a6c835 100644 --- a/luatz/init.lua +++ b/luatz/init.lua @@ -17,6 +17,11 @@ _M.time_in = function ( tz , now ) return _M.get_tz ( tz ):localize ( now ) end +_M.now = function ( ) + local ts = _M.gettime.gettime ( ) + return _M.timetable.new_from_timestamp ( ts ) +end + --- C-like functions _M.gmtime = function ( ts ) -- 2.39.5 From ebcbc1838c17993801dc53fee28a21d05f92aacc Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 17:01:43 -0400 Subject: [PATCH 12/16] doc/timetable: Document `normalise` fractional behaviour --- doc/timetable.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/timetable.md b/doc/timetable.md index 845c787..49fe046 100644 --- a/doc/timetable.md +++ b/doc/timetable.md @@ -39,9 +39,17 @@ Returns a new independent instance of an existing timetable object. ### `:normalise ( )` -Mutates the current object's time and date components so that they lie within 'normal' +Mutates the current object's time and date components so that are integers within 'normal' ranges e.g. `month` is `1`-`12`; `min` is `0`-`59` +First, fractional parts are propagated down. +e.g. `.month=6.5` `.day=1` (which could be read as "the first day after the middle of June") +normalises to `.month=2` `.day=16` + +Second, any fields outside of their normal ranges are propagated up +e.g. `.hour=10` `.min=100` (100 minutes past 10am) +normalises to `.hour=11` `.min=40` + ### `:rfc_3339 ( )` and `__tostring` metamethod -- 2.39.5 From 6058aa9e63278e4ae7400c6f8b91540718821d17 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 29 Aug 2014 17:32:02 -0400 Subject: [PATCH 13/16] .gitignore: Ignore built rocks --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa08b8c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +luatz-*.rock -- 2.39.5 From 38cb1f49b0e0be7018298018bb69e8fa3f785ad9 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Sun, 9 Nov 2014 02:11:55 -0500 Subject: [PATCH 14/16] luatz/timetable: Fix `rfc_3339()` bad rounding behaviour. Closes issue #4 --- luatz/timetable.lua | 5 +++-- spec/timetable_spec.lua | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/luatz/timetable.lua b/luatz/timetable.lua index fc89fca..7058d7f 100644 --- a/luatz/timetable.lua +++ b/luatz/timetable.lua @@ -171,8 +171,9 @@ function timetable_methods:timestamp ( ) end function timetable_methods:rfc_3339 ( ) - -- %06.3f gives 3 (=6-3) digits after decimal - return strformat ( "%04u-%02u-%02uT%02u:%02u:%06.3f" , self:unpack ( ) ) + local year , month , day , hour , min , sec = self:unpack ( ) + local sec , msec = borrow ( sec , 0 , 1000 ) + return strformat ( "%04u-%02u-%02uT%02u:%02u:%02d.%03d" , year , month , day , hour , min , sec , msec ) end function timetable_methods:strftime ( format_string ) diff --git a/spec/timetable_spec.lua b/spec/timetable_spec.lua index 569864f..7f6c704 100644 --- a/spec/timetable_spec.lua +++ b/spec/timetable_spec.lua @@ -104,4 +104,11 @@ describe ( "Timetable library" , function ( ) round_trip_add(timetable.new(2014,8,28,19,23,0), "month", 0.4) round_trip_add(timetable.new(2014,14.5,28,0,0,0), "month", 0.4) end ) + + it("#rfc_3339 doesn't round seconds up to 60 (issue #4)", function() + assert.same("2014-11-04T22:55:59.999", timetable.new_from_timestamp(1415141759.999911111):rfc_3339()) + assert.same("1970-01-01T00:00:59.999", timetable.new_from_timestamp(59.9999999):rfc_3339()) + assert.same("1969-12-31T23:59:59.999", timetable.new_from_timestamp(-0.001):rfc_3339()) + assert.same("1969-12-31T23:59:00.000", timetable.new_from_timestamp(-59.9999999):rfc_3339()) + end) end ) -- 2.39.5 From a3b2f88d60b3f1d2275170c616fc052b7a5df51a Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 16 Dec 2014 19:19:56 -0500 Subject: [PATCH 15/16] luatz/parse: Fix unbalanced parens in comment --- luatz/parse.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luatz/parse.lua b/luatz/parse.lua index f5cf735..0b3b2dd 100644 --- a/luatz/parse.lua +++ b/luatz/parse.lua @@ -27,7 +27,7 @@ local function rfc_3339 ( str , init ) if hour_offset then tz_offset = tonumber ( hour_offset ) * 3600 + tonumber ( min_offset ) * 60 else - -- Invalid RFC 3339 timestamp offset (should be Z or (+/-)hour:min + -- Invalid RFC 3339 timestamp offset (should be Z or (+/-)hour:min) -- tz_offset will be nil end end -- 2.39.5 From 97f3375906b56c5dfaddfcdb5208002919006ad1 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 2 Jan 2015 16:48:04 -0500 Subject: [PATCH 16/16] luatz/tzfile: Use string.unpack when available (Lua 5.3+) --- luatz/tzfile.lua | 53 +++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/luatz/tzfile.lua b/luatz/tzfile.lua index a3fa794..d4285c4 100644 --- a/luatz/tzfile.lua +++ b/luatz/tzfile.lua @@ -1,30 +1,45 @@ local tz_info_mt = require "luatz.tzinfo".tz_info_mt local tt_info_mt = require "luatz.tzinfo".tt_info_mt +local read_int32be, read_int64be -local function read_int32be ( fd ) - local data , err = fd:read ( 4 ) - if data == nil then return nil , err end - local o1 , o2 , o3 , o4 = data:byte ( 1 , 4 ) +if string.unpack then -- Only available in Lua 5.3+ + function read_int32be(fd) + local data, err = fd:read(4) + if data == nil then return nil, err end + return string.unpack(">i4", data) + end - local unsigned = o4 + o3*2^8 + o2*2^16 + o1*2^24 - if unsigned >= 2^31 then - return unsigned - 2^32 - else - return unsigned + function read_int64be(fd) + local data, err = fd:read(8) + if data == nil then return nil, err end + return string.unpack(">i8", data) + end +else + function read_int32be(fd) + local data, err = fd:read(4) + if data == nil then return nil, err end + local o1, o2, o3, o4 = data:byte(1, 4) + + local unsigned = o4 + o3*2^8 + o2*2^16 + o1*2^24 + if unsigned >= 2^31 then + return unsigned - 2^32 + else + return unsigned + end end -end -local function read_int64be ( fd ) - local data , err = fd:read ( 8 ) - if data == nil then return nil , err end - local o1 , o2 , o3 , o4 , o5 , o6 , o7 , o8 = data:byte ( 1 , 8 ) + function read_int64be(fd) + local data, err = fd:read(8) + if data == nil then return nil, err end + local o1, o2, o3, o4, o5, o6, o7, o8 = data:byte(1, 8) - local unsigned = o8 + o7*2^8 + o6*2^16 + o5*2^24 + o4*2^32 + o3*2^40 + o2*2^48 + o1*2^56 - if unsigned >= 2^63 then - return unsigned - 2^64 - else - return unsigned + local unsigned = o8 + o7*2^8 + o6*2^16 + o5*2^24 + o4*2^32 + o3*2^40 + o2*2^48 + o1*2^56 + if unsigned >= 2^63 then + return unsigned - 2^64 + else + return unsigned + end end end -- 2.39.5