From 74d5923767607c935fff45129486ff9c4251c283 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Wed, 6 Dec 2017 17:31:40 +1100 Subject: [PATCH] Move to consistent whitespace style --- examples/date_arithmetic.lua | 32 +++--- examples/os_date.lua | 14 +-- luatz/gettime.lua | 42 +++---- luatz/init.lua | 34 +++--- luatz/parse.lua | 28 ++--- luatz/strftime.lua | 198 ++++++++++++++++---------------- luatz/timetable.lua | 212 +++++++++++++++++------------------ luatz/tzcache.lua | 24 ++-- luatz/tzfile.lua | 142 +++++++++++------------ luatz/tzinfo.lua | 68 +++++------ spec/parse_spec.lua | 14 +-- spec/timetable_spec.lua | 178 ++++++++++++++--------------- 12 files changed, 493 insertions(+), 493 deletions(-) diff --git a/examples/date_arithmetic.lua b/examples/date_arithmetic.lua index c1148fb..4065122 100644 --- a/examples/date_arithmetic.lua +++ b/examples/date_arithmetic.lua @@ -1,33 +1,33 @@ 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 ) +local function ts2tt(ts) + return luatz.timetable.new_from_timestamp(ts) end -- Get the current time in UTC -local utcnow = luatz.time ( ) -local now = ts2tt ( utcnow ) -print ( now , "now (UTC)" ) +local utcnow = luatz.time() +local now = ts2tt(utcnow) +print(now, "now (UTC)") -- Get a new time object 6 months from now -local x = now:clone ( ) +local x = now:clone() x.month = x.month + 6 -x:normalise ( ) -print ( x , "6 months from now" ) +x:normalise() +print(x, "6 months from now") -- Find out what time it is in Melbourne at the moment -local melbourne = luatz.get_tz ( "Australia/Melbourne" ) -local now_in_melbourne = ts2tt ( melbourne:localise ( utcnow ) ) -print ( now_in_melbourne , "Melbourne" ) +local melbourne = luatz.get_tz("Australia/Melbourne") +local now_in_melbourne = ts2tt(melbourne:localise(utcnow)) +print(now_in_melbourne, "Melbourne") -- Six months from now in melbourne (so month is incremented; but still the same time) -local m = now_in_melbourne:clone ( ) +local m = now_in_melbourne:clone() m.month = m.month + 6 -m:normalise ( ) -print ( m , "6 months from now in melbourne" ) +m:normalise() +print(m, "6 months from now in melbourne") -- Convert time back to utc; a daylight savings transition may have taken place! -- There may be 2 results, but for we'll ignore the second possibility -local c , _ = melbourne:utctime ( m:timestamp( ) ) -print ( ts2tt ( c ) , "6 months from now in melbourne converted to utc" ) +local c, _ = melbourne:utctime(m:timestamp()) +print(ts2tt(c), "6 months from now in melbourne converted to utc") diff --git a/examples/os_date.lua b/examples/os_date.lua index deac08b..ad254ce 100644 --- a/examples/os_date.lua +++ b/examples/os_date.lua @@ -6,19 +6,19 @@ local gettime = require "luatz.gettime".gettime local new_from_timestamp = require "luatz.timetable".new_from_timestamp local get_tz = require "luatz.tzcache".get_tz -local function os_date ( format_string , timestamp ) +local function os_date(format_string, timestamp) format_string = format_string or "%c" - timestamp = timestamp or gettime ( ) - if format_string:sub ( 1 , 1 ) == "!" then -- UTC - format_string = format_string:sub ( 2 ) + timestamp = timestamp or gettime() + if format_string:sub(1, 1) == "!" then -- UTC + format_string = format_string:sub(2) else -- Localtime - timestamp = get_tz ( ):localise ( timestamp ) + timestamp = get_tz():localise(timestamp) end - local tt = new_from_timestamp ( timestamp ) + local tt = new_from_timestamp(timestamp) if format_string == "*t" then return tt else - return tt:strftime ( format_string ) + return tt:strftime(format_string) end end diff --git a/luatz/gettime.lua b/luatz/gettime.lua index d3eee80..4d6f45a 100644 --- a/luatz/gettime.lua +++ b/luatz/gettime.lua @@ -1,34 +1,34 @@ -local _M = { } +local _M = {} -_M.source , _M.resolution , _M.gettime = (function() - local has_syscall , syscall = pcall ( require , "syscall" ) +_M.source, _M.resolution, _M.gettime = (function() + local has_syscall, syscall = pcall(require, "syscall") if has_syscall and syscall.clock_gettime and syscall.c.CLOCK then local clock_id = syscall.c.CLOCK.REALTIME - local function timespec_to_number ( timespec ) - return tonumber ( timespec.tv_sec ) + tonumber ( timespec.tv_nsec ) * 1e-9 + local function timespec_to_number(timespec) + return tonumber(timespec.tv_sec) + tonumber(timespec.tv_nsec) * 1e-9 end - return "syscall.clock_gettime(CLOCK_REALTIME)" , - syscall.clock_getres and timespec_to_number ( syscall.clock_getres ( clock_id ) ) or 1e-9 , - function ( ) - return timespec_to_number ( syscall.clock_gettime ( clock_id ) ) + return "syscall.clock_gettime(CLOCK_REALTIME)", + syscall.clock_getres and timespec_to_number(syscall.clock_getres(clock_id)) or 1e-9, + function() + return timespec_to_number(syscall.clock_gettime(clock_id)) end end - local has_unix , unix = pcall ( require , "unix" ) + local has_unix, unix = pcall(require, "unix") -- On Apple devices lunix only uses gettimeofday() if has_unix and unix.clock_gettime and unix.uname and unix.uname().sysname ~= "Darwin" then - return "unix.clock_gettime(CLOCK_REALTIME)" , 1e-9 , function ( ) - return unix.clock_gettime ( ) + return "unix.clock_gettime(CLOCK_REALTIME)", 1e-9, function() + return unix.clock_gettime() end end if has_syscall and syscall.gettimeofday then - local function timeval_to_number ( timeval ) - return tonumber ( timeval.tv_sec ) + tonumber ( timeval.tv_nsec ) * 1e-6 + local function timeval_to_number(timeval) + return tonumber(timeval.tv_sec) + tonumber(timeval.tv_nsec) * 1e-6 end - return "syscall.gettimeofday()" , 1e-6 , - function ( ) - return timeval_to_number ( syscall.gettimeofday ( ) ) + return "syscall.gettimeofday()", 1e-6, + function() + return timeval_to_number(syscall.gettimeofday()) end end @@ -36,18 +36,18 @@ _M.source , _M.resolution , _M.gettime = (function() return "unix.gettimeofday()", 1e-6, unix.gettimeofday end - local has_socket , socket = pcall ( require , "socket" ) + local has_socket, socket = pcall(require, "socket") if has_socket and socket.gettime then -- on windows, this uses GetSystemTimeAsFileTime, which has resolution of 1e-7 -- on linux, this uses gettimeofday, which has resolution of 1e-6 - return "socket.gettime()" , 1e-6 , socket.gettime + return "socket.gettime()", 1e-6, socket.gettime end if ngx and ngx.now then -- luacheck: ignore 113 - return "ngx.now()" , 1e-3 , ngx.now -- luacheck: ignore 113 + return "ngx.now()", 1e-3, ngx.now -- luacheck: ignore 113 end - return "os.time()" , 1 , os.time + return "os.time()", 1, os.time end)() return _M diff --git a/luatz/init.lua b/luatz/init.lua index 1a6c835..4423189 100644 --- a/luatz/init.lua +++ b/luatz/init.lua @@ -1,9 +1,9 @@ local _M = { - gettime = require "luatz.gettime" ; - parse = require "luatz.parse" ; - strftime = require "luatz.strftime" ; - timetable = require "luatz.timetable" ; - tzcache = require "luatz.tzcache" ; + gettime = require "luatz.gettime"; + parse = require "luatz.parse"; + strftime = require "luatz.strftime"; + timetable = require "luatz.timetable"; + tzcache = require "luatz.tzcache"; } --- Top-level aliases for common functions @@ -13,28 +13,28 @@ _M.get_tz = _M.tzcache.get_tz --- Handy functions -_M.time_in = function ( tz , now ) - return _M.get_tz ( tz ):localize ( now ) +_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 ) +_M.now = function() + local ts = _M.gettime.gettime() + return _M.timetable.new_from_timestamp(ts) end --- C-like functions -_M.gmtime = function ( ts ) - return _M.timetable.new_from_timestamp ( ts ) +_M.gmtime = function(ts) + return _M.timetable.new_from_timestamp(ts) end -_M.localtime = function ( ts ) - ts = _M.time_in ( nil , ts ) - return _M.gmtime ( ts ) +_M.localtime = function(ts) + ts = _M.time_in(nil, ts) + return _M.gmtime(ts) end -_M.ctime = function ( ts ) - return _M.strftime.asctime ( _M.localtime ( ts ) ) +_M.ctime = function(ts) + return _M.strftime.asctime(_M.localtime(ts)) end return _M diff --git a/luatz/parse.lua b/luatz/parse.lua index 648d538..089dd0e 100644 --- a/luatz/parse.lua +++ b/luatz/parse.lua @@ -5,36 +5,36 @@ local new_timetable = require "luatz.timetable".new -- Return value is not normalised (this preserves a leap second) -- If the timestamp is only partial (i.e. missing "Z" or time offset) then `tz_offset` will be nil -- TODO: Validate components are within their boundarys (e.g. 1 <= month <= 12) -local function rfc_3339 ( str , init ) - local year , month , day , hour , min , sec , patt_end = str:match ( "^(%d%d%d%d)%-(%d%d)%-(%d%d)[Tt](%d%d%.?%d*):(%d%d):(%d%d)()" , init ) -- luacheck: ignore 631 +local function rfc_3339(str, init) + local year, month, day, hour, min, sec, patt_end = str:match("^(%d%d%d%d)%-(%d%d)%-(%d%d)[Tt](%d%d%.?%d*):(%d%d):(%d%d)()", init) -- luacheck: ignore 631 if not year then return nil, "Invalid RFC 3339 timestamp" end - year = tonumber ( year ) - month = tonumber ( month ) - day = tonumber ( day ) - hour = tonumber ( hour ) - min = tonumber ( min ) - sec = tonumber ( sec ) + year = tonumber(year) + month = tonumber(month) + day = tonumber(day) + hour = tonumber(hour) + min = tonumber(min) + sec = tonumber(sec) - local tt = new_timetable ( year , month , day , hour , min , sec ) + local tt = new_timetable(year, month, day, hour, min, sec) local tz_offset - if str:match ("^[Zz]" , patt_end ) then + if str:match("^[Zz]", patt_end) then tz_offset = 0 else - local hour_offset , min_offset = str:match ( "^([+-]%d%d):(%d%d)" , patt_end ) + local hour_offset, min_offset = str:match("^([+-]%d%d):(%d%d)", patt_end) if hour_offset then - tz_offset = tonumber ( hour_offset ) * 3600 + tonumber ( min_offset ) * 60 + tz_offset = tonumber(hour_offset) * 3600 + tonumber(min_offset) * 60 else -- luacheck: ignore 542 -- Invalid RFC 3339 timestamp offset (should be Z or (+/-)hour:min) -- tz_offset will be nil end end - return tt , tz_offset + return tt, tz_offset end return { - rfc_3339 = rfc_3339 ; + rfc_3339 = rfc_3339; } diff --git a/luatz/strftime.lua b/luatz/strftime.lua index a65a706..223da0f 100644 --- a/luatz/strftime.lua +++ b/luatz/strftime.lua @@ -1,21 +1,21 @@ local strformat = string.format local floor = math.floor -local function idiv ( n , d ) - return floor ( n / d ) +local function idiv(n, d) + return floor(n / d) end local c_locale = { - abday = { "Sun" , "Mon" , "Tue" , "Wed" , "Thu" , "Fri" , "Sat" } ; - day = { "Sunday" , "Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" } ; - abmon = { "Jan" , "Feb" , "Mar" , "Apr" , "May" , "Jun" , "Jul" , "Aug" , "Sep" , "Oct" , "Nov" , "Dec" } ; - mon = { "January" , "February" , "March" , "April" , "May" , "June" , - "July" , "August" , "September" , "October" , "November" , "December" } ; - am_pm = { "AM" , "PM" } ; + abday = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + day = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; + abmon = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + mon = {"January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; + am_pm = {"AM", "PM"}; } --- ISO-8601 week logic -- ISO 8601 weekday as number with Monday as 1 (1-7) -local function iso_8601_weekday ( wday ) +local function iso_8601_weekday(wday) if wday == 1 then return 7 else @@ -24,7 +24,7 @@ local function iso_8601_weekday ( wday ) end local iso_8601_week do -- Years that have 53 weeks according to ISO-8601 - local long_years = { } + local long_years = {} for _, v in ipairs { 4, 9, 15, 20, 26, 32, 37, 43, 48, 54, 60, 65, 71, 76, 82, 88, 93, 99, 105, 111, 116, 122, 128, 133, 139, 144, 150, 156, 161, 167, @@ -32,179 +32,179 @@ local iso_8601_week do 257, 263, 268, 274, 280, 285, 291, 296, 303, 308, 314, 320, 325, 331, 336, 342, 348, 353, 359, 364, 370, 376, 381, 387, 392, 398 } do - long_years [ v ] = true + long_years[v] = true end - local function is_long_year ( year ) - return long_years [ year % 400 ] + local function is_long_year(year) + return long_years[year % 400] end - function iso_8601_week ( self ) - local wday = iso_8601_weekday ( self.wday ) + function iso_8601_week(self) + local wday = iso_8601_weekday(self.wday) local n = self.yday - wday local year = self.year if n < -3 then year = year - 1 - if is_long_year ( year ) then - return year , 53 , wday + if is_long_year(year) then + return year, 53, wday else - return year , 52 , wday + return year, 52, wday end - elseif n >= 361 and not is_long_year ( year ) then - return year + 1 , 1 , wday + elseif n >= 361 and not is_long_year(year) then + return year + 1, 1, wday else - return year , idiv ( n + 10 , 7 ) , wday + return year, idiv(n + 10, 7), wday end end end --- Specifiers -local t = { } -function t:a ( locale ) - return "%s" , locale.abday [ self.wday ] +local t = {} +function t:a(locale) + return "%s", locale.abday[self.wday] end -function t:A ( locale ) - return "%s" , locale.day [ self.wday ] +function t:A(locale) + return "%s", locale.day[self.wday] end -function t:b ( locale ) - return "%s" , locale.abmon [ self.month ] +function t:b(locale) + return "%s", locale.abmon[self.month] end -function t:B ( locale ) - return "%s" , locale.mon [ self.month ] +function t:B(locale) + return "%s", locale.mon[self.month] end -function t:c ( locale ) - return "%.3s %.3s%3d %.2d:%.2d:%.2d %d" , - locale.abday [ self.wday ] , locale.abmon [ self.month ] , - self.day , self.hour , self.min , self.sec , self.year +function t:c(locale) + return "%.3s %.3s%3d %.2d:%.2d:%.2d %d", + locale.abday[self.wday], locale.abmon[self.month], + self.day, self.hour, self.min, self.sec, self.year end -- Century -function t:C ( ) - return "%02d" , idiv ( self.year , 100 ) +function t:C() + return "%02d", idiv(self.year, 100) end -function t:d ( ) - return "%02d" , self.day +function t:d() + return "%02d", self.day end -- Short MM/DD/YY date, equivalent to %m/%d/%y -function t:D ( ) - return "%02d/%02d/%02d" , self.month , self.day , self.year % 100 +function t:D() + return "%02d/%02d/%02d", self.month, self.day, self.year % 100 end -function t:e ( ) - return "%2d" , self.day +function t:e() + return "%2d", self.day end -- Short YYYY-MM-DD date, equivalent to %Y-%m-%d -function t:F ( ) - return "%d-%02d-%02d" , self.year , self.month , self.day +function t:F() + return "%d-%02d-%02d", self.year, self.month, self.day end -- Week-based year, last two digits (00-99) -function t:g ( ) - return "%02d" , iso_8601_week ( self ) % 100 +function t:g() + return "%02d", iso_8601_week(self) % 100 end -- Week-based year -function t:G ( ) - return "%d" , iso_8601_week ( self ) +function t:G() + return "%d", iso_8601_week(self) end t.h = t.b -function t:H ( ) - return "%02d" , self.hour +function t:H() + return "%02d", self.hour end -function t:I ( ) - return "%02d" , (self.hour-1) % 12 + 1 +function t:I() + return "%02d", (self.hour-1) % 12 + 1 end -function t:j ( ) - return "%03d" , self.yday +function t:j() + return "%03d", self.yday end -function t:m ( ) - return "%02d" , self.month +function t:m() + return "%02d", self.month end -function t:M ( ) - return "%02d" , self.min +function t:M() + return "%02d", self.min end -- New-line character ('\n') -function t:n ( ) -- luacheck: ignore 212 +function t:n() -- luacheck: ignore 212 return "\n" end -function t:p ( locale ) +function t:p(locale) return self.hour < 12 and locale.am_pm[1] or locale.am_pm[2] end -- TODO: should respect locale -function t:r ( locale ) - return "%02d:%02d:%02d %s" , - (self.hour-1) % 12 + 1 , self.min , self.sec , +function t:r(locale) + return "%02d:%02d:%02d %s", + (self.hour-1) % 12 + 1, self.min, self.sec, self.hour < 12 and locale.am_pm[1] or locale.am_pm[2] end -- 24-hour HH:MM time, equivalent to %H:%M -function t:R ( ) - return "%02d:%02d" , self.hour , self.min +function t:R() + return "%02d:%02d", self.hour, self.min end -function t:s ( ) - return "%d" , self:timestamp ( ) +function t:s() + return "%d", self:timestamp() end -function t:S ( ) - return "%02d" , self.sec +function t:S() + return "%02d", self.sec end -- Horizontal-tab character ('\t') -function t:t ( ) -- luacheck: ignore 212 +function t:t() -- luacheck: ignore 212 return "\t" end -- ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S -function t:T ( ) - return "%02d:%02d:%02d" , self.hour , self.min , self.sec +function t:T() + return "%02d:%02d:%02d", self.hour, self.min, self.sec end -function t:u ( ) - return "%d" , iso_8601_weekday ( self.wday ) +function t:u() + return "%d", iso_8601_weekday(self.wday) end -- Week number with the first Sunday as the first day of week one (00-53) -function t:U ( ) - return "%02d" , idiv ( self.yday - self.wday + 7 , 7 ) +function t:U() + return "%02d", idiv(self.yday - self.wday + 7, 7) end -- ISO 8601 week number (00-53) -function t:V ( ) - return "%02d" , select ( 2 , iso_8601_week ( self ) ) +function t:V() + return "%02d", select(2, iso_8601_week(self)) end -- Weekday as a decimal number with Sunday as 0 (0-6) -function t:w ( ) - return "%d" , self.wday - 1 +function t:w() + return "%d", self.wday - 1 end -- Week number with the first Monday as the first day of week one (00-53) -function t:W ( ) - return "%02d" , idiv ( self.yday - iso_8601_weekday ( self.wday ) + 7 , 7 ) +function t:W() + return "%02d", idiv(self.yday - iso_8601_weekday(self.wday) + 7, 7) end -- TODO make t.x and t.X respect locale t.x = t.D t.X = t.T -function t:y ( ) - return "%02d" , self.year % 100 +function t:y() + return "%02d", self.year % 100 end -function t:Y ( ) - return "%d" , self.year +function t:Y() + return "%d", self.year end -- TODO timezones -function t:z ( ) -- luacheck: ignore 212 +function t:z() -- luacheck: ignore 212 return "+0000" end -function t:Z ( ) -- luacheck: ignore 212 +function t:Z() -- luacheck: ignore 212 return "GMT" end -- A literal '%' character. -t["%"] = function ( self ) -- luacheck: ignore 212 +t["%"] = function(self) -- luacheck: ignore 212 return "%%" end -local function strftime ( format_string , timetable ) - return ( string.gsub ( format_string , "%%([EO]?)(.)" , function ( locale_modifier , specifier ) - local func = t [ specifier ] +local function strftime(format_string, timetable) + return (string.gsub(format_string, "%%([EO]?)(.)", function(locale_modifier, specifier) + local func = t[specifier] if func then - return strformat ( func ( timetable , c_locale ) ) + return strformat(func(timetable, c_locale)) else - error ( "invalid conversation specifier '%"..locale_modifier..specifier.."'" , 3 ) + error("invalid conversation specifier '%"..locale_modifier..specifier.."'", 3) end - end ) ) + end)) end -local function asctime ( timetable ) +local function asctime(timetable) -- Equivalent to the format string "%c\n" - return strformat ( t.c ( timetable , c_locale ) ) .. "\n" + return strformat(t.c(timetable, c_locale)) .. "\n" end return { - strftime = strftime ; - asctime = asctime ; + strftime = strftime; + asctime = asctime; } diff --git a/luatz/timetable.lua b/luatz/timetable.lua index 812d497..1a304e2 100644 --- a/luatz/timetable.lua +++ b/luatz/timetable.lua @@ -14,16 +14,16 @@ local idiv do end -local mon_lengths = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +local mon_lengths = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} -- Number of days in year until start of month; not corrected for leap years -local months_to_days_cumulative = { 0 } +local months_to_days_cumulative = {0} for i = 2, 12 do - months_to_days_cumulative [ i ] = months_to_days_cumulative [ i-1 ] + mon_lengths [ i-1 ] + months_to_days_cumulative[i] = months_to_days_cumulative[i-1] + mon_lengths[i-1] end -- For Sakamoto's Algorithm (day of week) local sakamoto = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; -local function is_leap ( y ) +local function is_leap(y) if (y % 4) ~= 0 then return false elseif (y % 100) ~= 0 then @@ -33,72 +33,72 @@ local function is_leap ( y ) end end -local function month_length ( m , y ) +local function month_length(m, y) if m == 2 then - return is_leap ( y ) and 29 or 28 + return is_leap(y) and 29 or 28 else - return mon_lengths [ m ] + return mon_lengths[m] end end -local function leap_years_since ( year ) - return idiv ( year , 4 ) - idiv ( year , 100 ) + idiv ( year , 400 ) +local function leap_years_since(year) + return idiv(year, 4) - idiv(year, 100) + idiv(year, 400) end -local function day_of_year ( day , month , year ) - local yday = months_to_days_cumulative [ month ] - if month > 2 and is_leap ( year ) then +local function day_of_year(day, month, year) + local yday = months_to_days_cumulative[month] + if month > 2 and is_leap(year) then yday = yday + 1 end return yday + day end -local function day_of_week ( day , month , year ) +local function day_of_week(day, month, year) if month < 3 then year = year - 1 end - return ( year + leap_years_since ( year ) + sakamoto[month] + day ) % 7 + 1 + return(year + leap_years_since(year) + sakamoto[month] + day) % 7 + 1 end -local function borrow ( tens , units , base ) +local function borrow(tens, units, base) local frac = tens % 1 units = units + frac * base tens = tens - frac - return tens , units + return tens, units end -local function carry ( tens , units , base ) +local function carry(tens, units, base) if units >= base then - tens = tens + idiv ( units , base ) + tens = tens + idiv(units, base) units = units % base elseif units < 0 then - tens = tens + idiv ( units , base ) - units = ( base + units ) % base + tens = tens + idiv(units, base) + units = (base + units) % base end - return tens , units + return tens, units end -- Modify parameters so they all fit within the "normal" range -local function normalise ( year , month , day , hour , min , sec ) +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 + month, day = month - 1, day - 1 -- Convert everything (except seconds) to an integer -- by propagating fractional components down. - year , month = borrow ( year , month , 12 ) + 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 ) + 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 ) + min , sec = carry(min , sec , 60) -- TODO: consider leap seconds? + hour , min = carry(hour, min , 60) + day , hour = carry(day , hour, 24) -- 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 @@ -108,13 +108,13 @@ local function normalise ( year , month , day , hour , min , sec ) year = year - 1 month = 11 end - day = day + month_length ( month + 1 , year ) + day = day + month_length(month + 1, year) end - year , month = carry ( year , month , 12 ) + year, month = carry(year, month, 12) -- TODO[OPTIMIZE]: This could potentially be slow if `day` is very large while true do - local i = month_length ( month + 1 , year ) + local i = month_length(month + 1, year) if day < i then break end day = day - i month = month + 1 @@ -126,129 +126,129 @@ local function normalise ( year , month , day , hour , min , sec ) -- 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 + month, day = month + 1, day + 1 - return year , month , day , hour , min , sec + return year, month, day, hour, min, sec end -local leap_years_since_1970 = leap_years_since ( 1970 ) -local function timestamp ( year , month , day , hour , min , sec ) - year , month , day , hour , min , sec = normalise ( year , month , day , hour , min , sec ) +local leap_years_since_1970 = leap_years_since(1970) +local function timestamp(year, month, day, hour, min, sec) + year, month, day, hour, min, sec = normalise(year, month, day, hour, min, sec) - local days_since_epoch = day_of_year ( day , month , year ) - + 365 * ( year - 1970 ) + local days_since_epoch = day_of_year(day, month, year) + + 365 * (year - 1970) -- Each leap year adds one day - + ( leap_years_since ( year - 1 ) - leap_years_since_1970 ) - 1 + + (leap_years_since(year - 1) - leap_years_since_1970) - 1 return days_since_epoch * (60*60*24) - + hour * (60*60) - + min * 60 + + hour * (60*60) + + min * 60 + sec end -local timetable_methods = { } +local timetable_methods = {} -function timetable_methods:unpack ( ) - return assert ( self.year , "year required" ) , - assert ( self.month , "month required" ) , - assert ( self.day , "day required" ) , - self.hour or 12 , - self.min or 0 , - self.sec or 0 , - self.yday , +function timetable_methods:unpack() + return assert(self.year , "year required"), + assert(self.month, "month required"), + assert(self.day , "day required"), + self.hour or 12, + self.min or 0, + self.sec or 0, + self.yday, self.wday end -function timetable_methods:normalise ( ) - local year , month , day - year , month , day , self.hour , self.min , self.sec = normalise ( self:unpack ( ) ) +function timetable_methods:normalise() + local year, month, day + year, month, day, self.hour, self.min, self.sec = normalise(self:unpack()) self.day = day self.month = month self.year = year - self.yday = day_of_year ( day , month , year ) - self.wday = day_of_week ( day , month , year ) + self.yday = day_of_year(day, month, year) + self.wday = day_of_week(day, month, year) return self end timetable_methods.normalize = timetable_methods.normalise -- American English -function timetable_methods:timestamp ( ) - return timestamp ( self:unpack ( ) ) +function timetable_methods:timestamp() + return timestamp(self:unpack()) end -function timetable_methods:rfc_3339 ( ) +function timetable_methods:rfc_3339() local year, month, day, hour, min, fsec = self:unpack() local sec, msec = borrow(fsec, 0, 1000) msec = math.floor(msec) - return strformat ( "%04u-%02u-%02uT%02u:%02u:%02d.%03d" , year , month , day , hour , min , sec , msec ) + return strformat("%04u-%02u-%02uT%02u:%02u:%02d.%03d", year, month, day, hour, min, sec, msec) end -function timetable_methods:strftime ( format_string ) - return strftime ( format_string , self ) +function timetable_methods:strftime(format_string) + return strftime(format_string, self) end local timetable_mt -local function coerce_arg ( t ) - if getmetatable ( t ) == timetable_mt then - return t:timestamp ( ) +local function coerce_arg(t) + if getmetatable(t) == timetable_mt then + return t:timestamp() end return t end timetable_mt = { - __index = timetable_methods ; - __tostring = timetable_methods.rfc_3339 ; - __eq = function ( a , b ) - return a:timestamp ( ) == b:timestamp ( ) - end ; - __lt = function ( a , b ) - return a:timestamp ( ) < b:timestamp ( ) - end ; - __sub = function ( a , b ) - return coerce_arg ( a ) - coerce_arg ( b ) - end ; + __index = timetable_methods; + __tostring = timetable_methods.rfc_3339; + __eq = function(a, b) + return a:timestamp() == b:timestamp() + end; + __lt = function(a, b) + return a:timestamp() < b:timestamp() + end; + __sub = function(a, b) + return coerce_arg(a) - coerce_arg(b) + end; } -local function cast_timetable ( tm ) - return setmetatable ( tm , timetable_mt ) +local function cast_timetable(tm) + return setmetatable(tm, timetable_mt) end -local function new_timetable ( year , month , day , hour , min , sec , yday , wday ) +local function new_timetable(year, month, day, hour, min, sec, yday, wday) return cast_timetable { - year = year ; - month = month ; - day = day ; - hour = hour ; - min = min ; - sec = sec ; - yday = yday ; - wday = wday ; + year = year; + month = month; + day = day; + hour = hour; + min = min; + sec = sec; + yday = yday; + wday = wday; } end -function timetable_methods:clone ( ) - return new_timetable ( self:unpack ( ) ) +function timetable_methods:clone() + return new_timetable(self:unpack()) end -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 ) +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 ):normalise ( ) + return new_timetable(1970, 1, 1, 0, 0, ts):normalise() end return { - is_leap = is_leap ; - day_of_year = day_of_year ; - day_of_week = day_of_week ; - normalise = normalise ; - timestamp = timestamp ; - - new = new_timetable ; - new_from_timestamp = new_from_timestamp ; - cast = cast_timetable ; - timetable_mt = timetable_mt ; + is_leap = is_leap; + day_of_year = day_of_year; + day_of_week = day_of_week; + normalise = normalise; + timestamp = timestamp; + + new = new_timetable; + new_from_timestamp = new_from_timestamp; + cast = cast_timetable; + timetable_mt = timetable_mt; } diff --git a/luatz/tzcache.lua b/luatz/tzcache.lua index 98ced26..ae32dce 100644 --- a/luatz/tzcache.lua +++ b/luatz/tzcache.lua @@ -2,34 +2,34 @@ local read_tzfile = require "luatz.tzfile".read_tzfile local base_zoneinfo_path = "/usr/share/zoneinfo/" local local_zoneinfo_path = "/etc/localtime" -local tz_cache = { } +local tz_cache = {} -local function name_to_zoneinfo_path ( name ) +local function name_to_zoneinfo_path(name) if name == nil then return local_zoneinfo_path - elseif name:sub ( 1 , 1 ) == "/" then + elseif name:sub(1, 1) == "/" then return name else return base_zoneinfo_path .. name end end -local function clear_tz_cache ( name ) - tz_cache [ name_to_zoneinfo_path ( name ) ] = nil +local function clear_tz_cache(name) + tz_cache[name_to_zoneinfo_path(name)] = nil end -local function get_tz ( name ) - local path = name_to_zoneinfo_path ( name ) +local function get_tz(name) + local path = name_to_zoneinfo_path(name) -- TODO: stat path - local tzinfo = tz_cache [ path ] + local tzinfo = tz_cache[path] if tzinfo == nil then - tzinfo = read_tzfile ( path ) - tz_cache [ path ] = tzinfo + tzinfo = read_tzfile(path) + tz_cache[path] = tzinfo end return tzinfo end return { - get_tz = get_tz ; - clear_tz_cache = clear_tz_cache ; + get_tz = get_tz; + clear_tz_cache = clear_tz_cache; } diff --git a/luatz/tzfile.lua b/luatz/tzfile.lua index 2d64d36..e57db6d 100644 --- a/luatz/tzfile.lua +++ b/luatz/tzfile.lua @@ -45,11 +45,11 @@ else -- luacheck: pop end end -local function read_flags ( fd , n ) - local data , err = fd:read ( n ) - if data == nil then return nil , err end +local function read_flags(fd, n) + local data, err = fd:read(n) + if data == nil then return nil, err end - local res = { } + local res = {} for i=1, n do res[i] = data:byte(i,i) ~= 0 end @@ -57,60 +57,60 @@ local function read_flags ( fd , n ) end local fifteen_nulls = ("\0"):rep(15) -local function read_tz ( fd ) - assert ( fd:read(4) == "TZif" , "Invalid TZ file" ) - local version = assert ( fd:read(1) ) +local function read_tz(fd) + assert(fd:read(4) == "TZif", "Invalid TZ file") + local version = assert(fd:read(1)) if version == "\0" or version == "2" or version == "3" then local MIN_TIME = -2^32+1 - assert ( assert ( fd:read(15) ) == fifteen_nulls , "Expected 15 nulls" ) + assert(assert(fd:read(15)) == fifteen_nulls, "Expected 15 nulls") -- The number of UTC/local indicators stored in the file. - local tzh_ttisgmtcnt = assert ( read_int32be ( fd ) ) + local tzh_ttisgmtcnt = assert(read_int32be(fd)) -- The number of standard/wall indicators stored in the file. - local tzh_ttisstdcnt = assert ( read_int32be ( fd ) ) + local tzh_ttisstdcnt = assert(read_int32be(fd)) -- The number of leap seconds for which data is stored in the file. - local tzh_leapcnt = assert ( read_int32be ( fd ) ) + local tzh_leapcnt = assert(read_int32be(fd)) -- The number of "transition times" for which data is stored in the file. - local tzh_timecnt = assert ( read_int32be ( fd ) ) + local tzh_timecnt = assert(read_int32be(fd)) -- The number of "local time types" for which data is stored in the file (must not be zero). - local tzh_typecnt = assert ( read_int32be ( fd ) ) + local tzh_typecnt = assert(read_int32be(fd)) -- The number of characters of "timezone abbreviation strings" stored in the file. - local tzh_charcnt = assert ( read_int32be ( fd ) ) + local tzh_charcnt = assert(read_int32be(fd)) - local transition_times = { } + local transition_times = {} for i=1, tzh_timecnt do - transition_times [ i ] = assert ( read_int32be ( fd ) ) + transition_times[i] = assert(read_int32be(fd)) end - local transition_time_ind = { assert ( fd:read ( tzh_timecnt ) ):byte ( 1 , -1 ) } + local transition_time_ind = {assert(fd:read(tzh_timecnt)):byte(1, -1)} - local ttinfos = { } + local ttinfos = {} for i=1, tzh_typecnt do - ttinfos [ i ] = { - gmtoff = assert ( read_int32be ( fd ) ) ; - isdst = assert ( fd:read ( 1 ) ) ~= "\0" ; - abbrind = assert ( fd:read ( 1 ) ):byte ( ) ; + ttinfos[i] = { + gmtoff = assert(read_int32be(fd)); + isdst = assert(fd:read(1)) ~= "\0"; + abbrind = assert(fd:read(1)):byte(); } end - local abbreviations = assert ( fd:read ( tzh_charcnt ) ) + local abbreviations = assert(fd:read(tzh_charcnt)) - local leap_seconds = { } -- luacheck: ignore 241 + local leap_seconds = {} -- luacheck: ignore 241 for i=1, tzh_leapcnt do - leap_seconds [ i ] = { - offset = assert ( read_int32be ( fd ) ) ; - n = assert ( read_int32be ( fd ) ) ; + leap_seconds[i] = { + offset = assert(read_int32be(fd)); + n = assert(read_int32be(fd)); } end - local isstd = assert ( read_flags ( fd , tzh_ttisstdcnt ) ) + local isstd = assert(read_flags(fd, tzh_ttisstdcnt)) - local isgmt = assert ( read_flags ( fd , tzh_ttisgmtcnt ) ) + local isgmt = assert(read_flags(fd, tzh_ttisgmtcnt)) local TZ @@ -121,56 +121,56 @@ local function read_tz ( fd ) ]] assert(fd:read(4) == "TZif") assert(fd:read(1) == version) - assert ( assert ( fd:read(15) ) == fifteen_nulls , "Expected 15 nulls" ) + assert(assert(fd:read(15)) == fifteen_nulls, "Expected 15 nulls") MIN_TIME = -2^64+1 -- The number of UTC/local indicators stored in the file. - tzh_ttisgmtcnt = assert ( read_int32be ( fd ) ) + tzh_ttisgmtcnt = assert(read_int32be(fd)) -- The number of standard/wall indicators stored in the file. - tzh_ttisstdcnt = assert ( read_int32be ( fd ) ) + tzh_ttisstdcnt = assert(read_int32be(fd)) -- The number of leap seconds for which data is stored in the file. - tzh_leapcnt = assert ( read_int32be ( fd ) ) + tzh_leapcnt = assert(read_int32be(fd)) -- The number of "transition times" for which data is stored in the file. - tzh_timecnt = assert ( read_int32be ( fd ) ) + tzh_timecnt = assert(read_int32be(fd)) -- The number of "local time types" for which data is stored in the file (must not be zero). - tzh_typecnt = assert ( read_int32be ( fd ) ) + tzh_typecnt = assert(read_int32be(fd)) -- The number of characters of "timezone abbreviation strings" stored in the file. - tzh_charcnt = assert ( read_int32be ( fd ) ) + tzh_charcnt = assert(read_int32be(fd)) - transition_times = { } + transition_times = {} for i=1, tzh_timecnt do - transition_times [ i ] = assert ( read_int64be ( fd ) ) + transition_times[i] = assert(read_int64be(fd)) end - transition_time_ind = { assert ( fd:read ( tzh_timecnt ) ):byte ( 1 , -1 ) } + transition_time_ind = {assert(fd:read(tzh_timecnt)):byte(1, -1)} - ttinfos = { } + ttinfos = {} for i=1, tzh_typecnt do - ttinfos [ i ] = { - gmtoff = assert ( read_int32be ( fd ) ) ; - isdst = assert ( fd:read ( 1 ) ) ~= "\0" ; - abbrind = assert ( fd:read ( 1 ) ):byte ( ) ; + ttinfos[i] = { + gmtoff = assert(read_int32be(fd)); + isdst = assert(fd:read(1)) ~= "\0"; + abbrind = assert(fd:read(1)):byte(); } end - abbreviations = assert ( fd:read ( tzh_charcnt ) ) + abbreviations = assert(fd:read(tzh_charcnt)) - leap_seconds = { } + leap_seconds = {} for i=1, tzh_leapcnt do - leap_seconds [ i ] = { - offset = assert ( read_int64be ( fd ) ) ; - n = assert ( read_int32be ( fd ) ) ; + leap_seconds[i] = { + offset = assert(read_int64be(fd)); + n = assert(read_int32be(fd)); } end - isstd = assert ( read_flags ( fd , tzh_ttisstdcnt ) ) + isstd = assert(read_flags(fd, tzh_ttisstdcnt)) - isgmt = assert ( read_flags ( fd , tzh_ttisgmtcnt ) ) + isgmt = assert(read_flags(fd, tzh_ttisgmtcnt)) --[[ After the second header and data comes a newline-enclosed, POSIX-TZ-environment-variable-style string @@ -188,20 +188,20 @@ local function read_tz ( fd ) between daylight saving and standard time. ]] - assert ( assert ( fd:read ( 1 ) ) == "\n" , "Expected newline at end of version 2 header" ) + assert(assert(fd:read(1)) == "\n", "Expected newline at end of version 2 header") - TZ = assert ( fd:read ( "*l" ) ) + TZ = assert(fd:read("*l")) if #TZ == 0 then TZ = nil end end for i=1, tzh_typecnt do - local v = ttinfos [ i ] - v.abbr = abbreviations:sub ( v.abbrind+1 , v.abbrind+3 ) - v.isstd = isstd [ i ] or false - v.isgmt = isgmt [ i ] or false - setmetatable ( v , tt_info_mt ) + local v = ttinfos[i] + v.abbr = abbreviations:sub(v.abbrind+1, v.abbrind+3) + v.isstd = isstd[i] or false + v.isgmt = isgmt[i] or false + setmetatable(v, tt_info_mt) end --[[ @@ -222,30 +222,30 @@ local function read_tz ( fd ) local res = { future = TZ; [0] = { - transition_time = MIN_TIME ; - info = ttinfos [ first ] ; + transition_time = MIN_TIME; + info = ttinfos[first]; } } for i=1, tzh_timecnt do - res [ i ] = { - transition_time = transition_times [ i ] ; - info = ttinfos [ transition_time_ind [ i ]+1 ] ; + res[i] = { + transition_time = transition_times[i]; + info = ttinfos[transition_time_ind[i]+1]; } end - return setmetatable ( res , tz_info_mt ) + return setmetatable(res, tz_info_mt) else - error ( "Unsupported version" ) + error("Unsupported version") end end -local function read_tzfile ( path ) - local fd = assert ( io.open ( path , "rb" ) ) - local tzinfo = read_tz ( fd ) - fd:close ( ) +local function read_tzfile(path) + local fd = assert(io.open(path, "rb")) + local tzinfo = read_tz(fd) + fd:close() return tzinfo end return { - read_tz = read_tz ; - read_tzfile = read_tzfile ; + read_tz = read_tz; + read_tzfile = read_tzfile; } diff --git a/luatz/tzinfo.lua b/luatz/tzinfo.lua index 3ff0a07..e37483f 100644 --- a/luatz/tzinfo.lua +++ b/luatz/tzinfo.lua @@ -1,51 +1,51 @@ local gettime = require "luatz.gettime".gettime local timetable_mt = require "luatz.timetable".timetable_mt -local function to_timestamp ( o ) - if type ( o ) == "number" then +local function to_timestamp(o) + if type(o) == "number" then return o - elseif getmetatable ( o ) == timetable_mt then - return o:timestamp ( ) + elseif getmetatable(o) == timetable_mt then + return o:timestamp() end end local tz_info_methods = { } local tz_info_mt = { __name = "luatz.tz_info"; - __index = tz_info_methods ; + __index = tz_info_methods; } local tt_info_mt = { __name = "luatz.tt_info"; - __tostring = function ( self ) - return string.format ( "tt_info:%s=%d" , self.abbr , self.gmtoff ) - end ; + __tostring = function(self) + return string.format("tt_info:%s=%d", self.abbr, self.gmtoff) + end; } -- Binary search -local function _find_current ( tzinfo , target , i , j ) +local function find_current(tzinfo, target, i, j) if i >= j then return j end - local half = math.ceil ( (j+i) / 2 ) + local half = math.ceil((j+i) / 2) - if target >= tzinfo [ half ].transition_time then - return _find_current ( tzinfo , target , half , j ) + if target >= tzinfo[half].transition_time then + return find_current(tzinfo, target, half, j) else - return _find_current ( tzinfo , target , i , half-1 ) + return find_current(tzinfo, target, i, half-1) end end -local function find_current_local ( tzinfo , ts_local ) +local function find_current_local(tzinfo, ts_local) -- Find two best possibilities by searching back and forward a day (assumes transition is never by more than 24 hours) - local tz_first = _find_current ( tzinfo , ts_local-86400 , 0 , #tzinfo ) - local tz_last = _find_current ( tzinfo , ts_local+86400 , 0 , #tzinfo ) + local tz_first = find_current(tzinfo, ts_local-86400, 0, #tzinfo) + local tz_last = find_current(tzinfo, ts_local+86400, 0, #tzinfo) local n_candidates = tz_last - tz_first + 1 if n_candidates == 1 then return tz_first elseif n_candidates == 2 then - local tz_first_ob = tzinfo [ tz_first ] - local tz_last_ob = tzinfo [ tz_last ] + local tz_first_ob = tzinfo[tz_first] + local tz_last_ob = tzinfo[tz_last] local first_gmtoffset = tz_first_ob.info.gmtoff local last_gmtoffset = tz_last_ob .info.gmtoff @@ -61,37 +61,37 @@ local function find_current_local ( tzinfo , ts_local ) end -- If we get this far, the local time is ambiguous - return tz_first , tz_last + return tz_first, tz_last else - error ( "Too many transitions in a 2 day period" ) + error("Too many transitions in a 2 day period") end end -function tz_info_methods:find_current ( current ) - current = assert ( to_timestamp ( current ) , "invalid timestamp to :find_current" ) - return self [ _find_current ( self , current , 0 , #self ) ].info +function tz_info_methods:find_current(current) + current = assert(to_timestamp(current), "invalid timestamp to :find_current") + return self[find_current(self, current, 0, #self)].info end -function tz_info_methods:localise ( utc_ts ) - utc_ts = utc_ts or gettime ( ) - return utc_ts + self:find_current ( utc_ts ).gmtoff +function tz_info_methods:localise(utc_ts) + utc_ts = utc_ts or gettime() + return utc_ts + self:find_current(utc_ts).gmtoff end tz_info_methods.localize = tz_info_methods.localise -function tz_info_methods:utctime ( ts_local ) - ts_local = assert ( to_timestamp ( ts_local ) , "invalid timestamp to :utctime" ) - local tz1 , tz2 = find_current_local ( self , ts_local ) - tz1 = self [ tz1 ].info +function tz_info_methods:utctime(ts_local) + ts_local = assert(to_timestamp(ts_local), "invalid timestamp to :utctime") + local tz1, tz2 = find_current_local(self, ts_local) + tz1 = self[tz1].info if tz2 == nil then return ts_local - tz1.gmtoff else -- Local time is ambiguous - tz2 = self [ tz2 ].info + tz2 = self[tz2].info - return ts_local - tz2.gmtoff , ts_local - tz2.gmtoff + return ts_local - tz2.gmtoff, ts_local - tz2.gmtoff end end return { - tz_info_mt = tz_info_mt ; - tt_info_mt = tt_info_mt ; + tz_info_mt = tz_info_mt; + tt_info_mt = tt_info_mt; } diff --git a/spec/parse_spec.lua b/spec/parse_spec.lua index 89c9a26..e38ad38 100644 --- a/spec/parse_spec.lua +++ b/spec/parse_spec.lua @@ -1,17 +1,17 @@ -describe ( "Time parsing library" , function ( ) +describe("Time parsing library", function() local timetable = require "luatz.timetable" local parse = require "luatz.parse" - it ( "#RFC3339 parsing" , function ( ) - assert.same ( timetable.new(2013,10,22,14,17,02) , (parse.rfc_3339 "2013-10-22T14:17:02Z") ) + it("#RFC3339 parsing", function() + assert.same(timetable.new(2013,10,22,14,17,02), (parse.rfc_3339 "2013-10-22T14:17:02Z")) -- Numeric offsets accepted - assert.same ( { timetable.new(2013,10,22,14,17,02) , 10*3600 } , { parse.rfc_3339 "2013-10-22T14:17:02+10:00" } ) + assert.same({timetable.new(2013,10,22,14,17,02), 10*3600 }, {parse.rfc_3339 "2013-10-22T14:17:02+10:00" }) -- Missing offsets parse - assert.same ( timetable.new(2013,10,22,14,17,02) , (parse.rfc_3339 "2013-10-22T14:17:02") ) + assert.same(timetable.new(2013,10,22,14,17,02), (parse.rfc_3339 "2013-10-22T14:17:02")) -- Invalid assert.same(nil, (parse.rfc_3339 "an invalid timestamp")) - end ) -end ) + end) +end) diff --git a/spec/timetable_spec.lua b/spec/timetable_spec.lua index 6c9617e..3713391 100644 --- a/spec/timetable_spec.lua +++ b/spec/timetable_spec.lua @@ -1,108 +1,108 @@ -describe ( "Timetable library" , function ( ) +describe("Timetable library", function() local timetable = require "luatz.timetable" - local function native_normalise ( year , month , day ) - return os.date("*t",os.time{ - year = year ; - month = month ; - day = day ; + local function native_normalise(year, month, day) + return os.date("*t",os.time { + year = year; + month = month; + day = day; }) 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 ) - return assert.are.same ( - native_normalise ( year , month , day ).wday , - timetable.new ( year , month , day ):normalise().wday + 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) + return assert.are.same( + native_normalise(year, month, day).wday, + timetable.new(year, month, day):normalise().wday ) end - assert_same_wday ( 2013 , 7 , 23 ) - assert_same_wday ( 2013 , 7 , 24 ) - assert_same_wday ( 2013 , 7 , 25 ) - assert_same_wday ( 2013 , 7 , 26 ) - assert_same_wday ( 2013 , 7 , 27 ) - assert_same_wday ( 2013 , 7 , 28 ) - assert_same_wday ( 2013 , 7 , 29 ) - 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 ) - return assert ( tonumber ( assert ( io.popen ( - string.format('date -u -d "%d-%d-%d" +%%s', year , month , day ) - ) ):read "*l" ) ) + assert_same_wday(2013, 7, 23) + assert_same_wday(2013, 7, 24) + assert_same_wday(2013, 7, 25) + assert_same_wday(2013, 7, 26) + assert_same_wday(2013, 7, 27) + assert_same_wday(2013, 7, 28) + assert_same_wday(2013, 7, 29) + 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) + return assert(tonumber(assert(io.popen( + string.format('date -u -d "%d-%d-%d" +%%s', year, month, day) + )):read "*l")) end - it ( "#timestamp creation is valid" , function ( ) + it("#timestamp creation is valid", function() for y=1950,2013 do for m=1,12 do - assert.same ( native_timestamp ( y,m,1 ) , timetable.timestamp(y,m,1,0,0,0) ) + assert.same(native_timestamp(y,m,1), timetable.timestamp(y,m,1,0,0,0)) end end - end ) - - it ( "#normalise handles out of range days in a year" , function ( ) - assert.same({ 2014,1,1,0,0,0 }, { timetable.normalise(2013,1,366,0,0,0) }) - assert.same({ 2014,2,4,0,0,0 }, { timetable.normalise(2013,1,400,0,0,0) }) - assert.same({ 2017,2,3,0,0,0 }, { timetable.normalise(2016,1,400,0,0,0) }) - assert.same({ 2016,3,5,0,0,0 }, { timetable.normalise(2015,1,430,0,0,0) }) - assert.same({ 2017,3,5,0,0,0 }, { timetable.normalise(2016,1,430,0,0,0) }) - assert.same({ 2027,5,18,0,0,0 }, { timetable.normalise(2000,1,10000,0,0,0) }) - assert.same({ 29379,1,25,0,0,0 }, { timetable.normalise(2000,1,10000000,0,0,0) }) - end ) - - it ( "#normalise handles out of range days in a #month" , function ( ) - assert.same({ 2012,12,1,0,0,0 }, { timetable.normalise(2013,0,1,0,0,0) }) - assert.same({ 2016,6,1,0,0,0 }, { timetable.normalise(2013,42,1,0,0,0) }) + end) + + it("#normalise handles out of range days in a year", function() + assert.same({2014,1,1,0,0,0}, {timetable.normalise(2013,1,366,0,0,0)}) + assert.same({2014,2,4,0,0,0}, {timetable.normalise(2013,1,400,0,0,0)}) + assert.same({2017,2,3,0,0,0}, {timetable.normalise(2016,1,400,0,0,0)}) + assert.same({2016,3,5,0,0,0}, {timetable.normalise(2015,1,430,0,0,0)}) + assert.same({2017,3,5,0,0,0}, {timetable.normalise(2016,1,430,0,0,0)}) + assert.same({2027,5,18,0,0,0}, {timetable.normalise(2000,1,10000,0,0,0)}) + assert.same({29379,1,25,0,0,0}, {timetable.normalise(2000,1,10000000,0,0,0)}) + end) + + it("#normalise handles out of range days in a #month", function() + assert.same({2012,12,1,0,0,0}, {timetable.normalise(2013,0,1,0,0,0)}) + assert.same({2016,6,1,0,0,0}, {timetable.normalise(2013,42,1,0,0,0)}) -- Correct behaviour around leap days - assert.same({ 2012,3,23,0,0,0 }, { timetable.normalise(2012,2,52,0,0,0) }) - assert.same({ 2013,3,24,0,0,0 }, { timetable.normalise(2013,2,52,0,0,0) }) + assert.same({2012,3,23,0,0,0}, {timetable.normalise(2012,2,52,0,0,0)}) + assert.same({2013,3,24,0,0,0}, {timetable.normalise(2013,2,52,0,0,0)}) - assert.same({ 2012,2,27,0,0,0 }, { timetable.normalise(2012,3,-2,0,0,0) }) - assert.same({ 2013,2,26,0,0,0 }, { timetable.normalise(2013,3,-2,0,0,0) }) + assert.same({2012,2,27,0,0,0}, {timetable.normalise(2012,3,-2,0,0,0)}) + assert.same({2013,2,26,0,0,0}, {timetable.normalise(2013,3,-2,0,0,0)}) -- Also when more fields are out of range - assert.same({ 2016,7,22,0,0,0 }, { timetable.normalise(2013,42,52,0,0,0) }) - assert.same({ 2016,7,24,2,0,0 }, { timetable.normalise(2013,42,52,50,0,0) }) - end ) - - it ( "#normalise handles fractional #month" , function ( ) - assert.same({ 2015,2,15,0,0,0 } , { timetable.normalise(2014,14.5,1,0,0,0) }) - assert.same({ 2016,2,15,12,0,0 } , { timetable.normalise(2015,14.5,1,0,0,0) }) -- leap year, so hours is 12 - assert.same({ 2017,2,15,0,0,0 } , { timetable.normalise(2016,14.5,1,0,0,0) }) - end ) - - it ( "#normalise handles negative carry (issue #10)", function() - assert.same({ 1970,01,01,00,59,00 }, { timetable.normalise(1970,01,01,01,00,-60) }) - assert.same({ 1970,01,01,00,58,58 }, { timetable.normalise(1970,01,01,01,00,-62) }) - assert.same({ 1969,12,31,23,55,58 }, { timetable.normalise(1970,01,01,01,-63,-62) }) - assert.same({ 2017,02,3,0,0,0 }, { timetable.normalise(2017,02,13,0,-14400,0) }) - end ) - - it ( "#normalise handles negative day carry (issue #13)", function() - assert.same({ 2016,11,30,00,00,00 }, { timetable.normalise(2016,12,0,0,0,0) }) - assert.same({ 2017,11,30,00,00,00 }, { timetable.normalise(2017,12,0,0,0,0) }) - assert.same({ 2018,11,30,00,00,00 }, { timetable.normalise(2018,12,0,0,0,0) }) - end ) + assert.same({2016,7,22,0,0,0}, {timetable.normalise(2013,42,52,0,0,0)}) + assert.same({2016,7,24,2,0,0}, {timetable.normalise(2013,42,52,50,0,0)}) + end) + + it("#normalise handles fractional #month", function() + assert.same({2015,2,15,0,0,0}, {timetable.normalise(2014,14.5,1,0,0,0)}) + assert.same({2016,2,15,12,0,0}, {timetable.normalise(2015,14.5,1,0,0,0)}) -- leap year, so hours is 12 + assert.same({2017,2,15,0,0,0}, {timetable.normalise(2016,14.5,1,0,0,0)}) + end) + + it("#normalise handles negative carry (issue #10)", function() + assert.same({1970,01,01,00,59,00}, {timetable.normalise(1970,01,01,01,00,-60)}) + assert.same({1970,01,01,00,58,58}, {timetable.normalise(1970,01,01,01,00,-62)}) + assert.same({1969,12,31,23,55,58}, {timetable.normalise(1970,01,01,01,-63,-62)}) + assert.same({2017,02,3,0,0,0}, {timetable.normalise(2017,02,13,0,-14400,0)}) + end) + + it("#normalise handles negative day carry (issue #13)", function() + assert.same({2016,11,30,00,00,00}, {timetable.normalise(2016,12,0,0,0,0)}) + assert.same({2017,11,30,00,00,00}, {timetable.normalise(2017,12,0,0,0,0)}) + assert.same({2018,11,30,00,00,00}, {timetable.normalise(2018,12,0,0,0,0)}) + end) local function round_trip_add(t, field, x) local before = t:clone() @@ -112,11 +112,11 @@ describe ( "Timetable library" , function ( ) t:normalise(); assert.same(0, t-before) end - it ( "#normalise round trips" , function ( ) + 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) it("#rfc_3339 works with fractional milliseconds", function() -- on lua 5.3 this used to throw an error due to milliseconds not being an integer @@ -129,4 +129,4 @@ describe ( "Timetable library" , function ( ) 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 ) +end) -- 2.39.5