X-Git-Url: https://git.madduck.net/etc/awesome.git/blobdiff_plain/27e12c9a39aa33f8815964adedd036cd6703099f..ac89c4c58d68776dfec1a54c19077a58f1eb76c6:/luatz/tzfile.lua?ds=inline

diff --git a/luatz/tzfile.lua b/luatz/tzfile.lua
index a0f8da5..ec10bc0 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
 
@@ -43,7 +58,7 @@ 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) )
-	if version == "\0" or version == "2" then
+	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" )
@@ -95,12 +110,15 @@ local function read_tz ( fd )
 
 		local isgmt = assert ( read_flags ( fd , tzh_ttisgmtcnt ) )
 
-		if version == "2" then
+		local TZ
+
+		if version == "2" or version == "3" then
 			--[[
 			For version-2-format timezone files, the above header and data is followed by a second header and data,
 			identical in format except that eight bytes are used for each transition time or leap-second time.
 			]]
-			assert ( fd:read(5) == "TZif2" )
+			assert(fd:read(4) == "TZif")
+			assert(fd:read(1) == version)
 			assert ( assert ( fd:read(15) ) == fifteen_nulls , "Expected 15 nulls" )
 
 			MIN_TIME = -2^64+1
@@ -157,6 +175,23 @@ local function read_tz ( fd )
 			for use in handling instants after the last transition time stored in the file
 			(with nothing between the newlines if there is no POSIX representation for such instants).
 			]]
+
+			--[[
+			For version-3-format time zone files, the POSIX-TZ-style string may
+			use two minor extensions to the POSIX TZ format, as described in newtzset (3).
+			First, the hours part of its transition times may be signed and range from
+			-167 through 167 instead of the POSIX-required unsigned values
+			from 0 through 24.  Second, DST is in effect all year if it starts
+			January 1 at 00:00 and ends December 31 at 24:00 plus the difference
+			between daylight saving and standard time.
+			]]
+
+			assert ( assert ( fd:read ( 1 ) ) == "\n" , "Expected newline at end of version 2 header" )
+
+			TZ = assert ( fd:read ( "*l" ) )
+			if #TZ == 0 then
+				TZ = nil
+			end
 		end
 
 		for i=1, tzh_typecnt do
@@ -183,6 +218,7 @@ local function read_tz ( fd )
 		end
 
 		local res = {
+			future = TZ;
 			[0] = {
 				transition_time = MIN_TIME ;
 				info = ttinfos [ first ] ;