]> git.madduck.net Git - etc/awesome.git/blobdiff - src/tzinfo.lua

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

src/timetable: Fix timestamp function; add test
[etc/awesome.git] / src / tzinfo.lua
index 66589d930bf2d334fef22a1a1584ec233da7cb7b..34b704881ff9739e543ffdb100a3e3ae48aed52b 100644 (file)
@@ -1,3 +1,5 @@
+local gettime = require "luatz.gettime".gettime
+
 local tz_info_methods = { }
 local tz_info_mt = {
        __index = tz_info_methods ;
@@ -9,12 +11,46 @@ local function _find_current ( tzinfo , target , i , j )
 
        local half = math.ceil ( (j+i) / 2 )
 
-       if target > tzinfo [ half ].transition_time then
+       if target >= tzinfo [ half ].transition_time then
                return _find_current ( tzinfo , target , half , j )
        else
                return _find_current ( tzinfo , target , i , half-1 )
        end
 end
+
+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 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 first_gmtoffset = tz_first_ob.info.gmtoff
+               local last_gmtoffset  = tz_last_ob .info.gmtoff
+
+               local t_start = tz_last_ob.transition_time + first_gmtoffset
+               local t_end   = tz_last_ob.transition_time + last_gmtoffset
+
+               -- If timestamp is before start or after end
+               if ts_local < t_start then
+                       return tz_first
+               elseif ts_local > t_end then
+                       return tz_last
+               end
+
+               -- If we get this far, the local time is ambiguous
+               return tz_first , tz_last
+       else
+               error ( "Too many transitions in a 2 day period" )
+       end
+end
+
 function tz_info_methods:find_current ( current )
        return self [ _find_current ( self , current , 0 , #self ) ].info
 end
@@ -24,6 +60,18 @@ function tz_info_methods:localize ( utc_ts )
        return utc_ts + self:find_current ( utc_ts ).gmtoff
 end
 
+function tz_info_methods:utctime ( ts_local , is_dst )
+       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
+
+               return ts_local - tz2.gmtoff , ts_local - tz2.gmtoff
+       end
+end
+
 return {
        tz_info_mt = tz_info_mt ;
 }