a7edcfd025a975f0a188e163dcaa5b3d47cd49f9
[project/luci.git] / libs / http / luasrc / http / protocol / date.lua
1 --[[
2
3 HTTP protocol implementation for LuCI - date handling
4 (c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10         http://www.apache.org/licenses/LICENSE-2.0
11
12 $Id$
13
14 ]]--
15
16 module("luci.http.protocol.date", package.seeall)
17
18 local ucache = { }
19 local hcache = { }
20
21
22 MONTHS = {
23         "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
24         "Sep", "Oct", "Nov", "Dec"
25 }
26
27 -- This list is stolen from Perl's Time::Timezone
28 TZ = {
29         -- DST zones
30         ["brst"]  =   -2*3600;   -- Brazil Summer Time (East Daylight)
31         ["adt"]   =   -3*3600;   -- Atlantic Daylight
32         ["edt"]   =   -4*3600;   -- Eastern Daylight
33         ["cdt"]   =   -5*3600;   -- Central Daylight
34         ["mdt"]   =   -6*3600;   -- Mountain Daylight
35         ["pdt"]   =   -7*3600;   -- Pacific Daylight
36         ["ydt"]   =   -8*3600;   -- Yukon Daylight
37         ["hdt"]   =   -9*3600;   -- Hawaii Daylight
38         ["bst"]   =    1*3600;   -- British Summer
39         ["mest"]  =    2*3600;   -- Middle European Summer
40         ["sst"]   =    2*3600;   -- Swedish Summer
41         ["fst"]   =    2*3600;   -- French Summer
42         ["eest"]  =    3*3600;   -- Eastern European Summer
43         ["cest"]  =    2*3600;   -- Central European Daylight
44         ["wadt"]  =    8*3600;   -- West Australian Daylight
45         ["kdt"]   =   10*3600;   -- Korean Daylight
46         ["eadt"]  =   11*3600;   -- Eastern Australian Daylight
47         ["nzdt"]  =   13*3600;   -- New Zealand Daylight
48
49         -- zones
50         ["gmt"]   =   0;                 -- Greenwich Mean
51         ["ut"]    =   0;                 -- Universal (Coordinated)
52         ["utc"]   =   0;
53         ["wet"]   =   0;                 -- Western European
54         ["wat"]   =  -1*3600;    -- West Africa
55         ["azost"] =  -1*3600;    -- Azores Standard Time
56         ["cvt"]   =  -1*3600;    -- Cape Verde Time
57         ["at"]    =  -2*3600;    -- Azores
58         ["fnt"]   =  -2*3600;    -- Brazil Time (Extreme East - Fernando Noronha)
59         ["ndt"]   =  -2*3600+1800;-- Newfoundland Daylight
60         ["art"]   =  -3*3600;    -- Argentina Time
61         ["nft"]   =  -3*3600+1800;-- Newfoundland
62         ["mnt"]   =  -4*3600;    -- Brazil Time (West Standard - Manaus)
63         ["ewt"]   =  -4*3600;    -- U.S. Eastern War Time
64         ["ast"]   =  -4*3600;    -- Atlantic Standard
65         ["bot"]   =  -4*3600;    -- Bolivia Time
66         ["vet"]   =  -4*3600;    -- Venezuela Time
67         ["est"]   =  -5*3600;    -- Eastern Standard
68         ["cot"]   =  -5*3600;    -- Colombia Time
69         ["act"]   =  -5*3600;    -- Brazil Time (Extreme West - Acre)
70         ["pet"]   =  -5*3600;    -- Peru Time
71         ["cst"]   =  -6*3600;    -- Central Standard
72         ["cest"]  =   2*3600;    -- Central European Summer
73         ["mst"]   =  -7*3600;    -- Mountain Standard
74         ["pst"]   =  -8*3600;    -- Pacific Standard
75         ["yst"]   =  -9*3600;    -- Yukon Standard
76         ["hst"]   = -10*3600;    -- Hawaii Standard
77         ["cat"]   = -10*3600;    -- Central Alaska
78         ["ahst"]  = -10*3600;    -- Alaska-Hawaii Standard
79         ["taht"]  = -10*3600;    -- Tahiti Time
80         ["nt"]    = -11*3600;    -- Nome
81         ["idlw"]  = -12*3600;    -- International Date Line West
82         ["cet"]   =   1*3600;    -- Central European
83         ["mez"]   =   1*3600;    -- Central European (German)
84         ["met"]   =   1*3600;    -- Middle European
85         ["mewt"]  =   1*3600;    -- Middle European Winter
86         ["swt"]   =   1*3600;    -- Swedish Winter
87         ["set"]   =   1*3600;    -- Seychelles
88         ["fwt"]   =   1*3600;    -- French Winter
89         ["west"]  =   1*3600;    -- Western Europe Summer Time
90         ["eet"]   =   2*3600;    -- Eastern Europe; USSR Zone 1
91         ["ukr"]   =   2*3600;    -- Ukraine
92         ["sast"]  =   2*3600;    -- South Africa Standard Time
93         ["bt"]    =   3*3600;    -- Baghdad; USSR Zone 2
94         ["eat"]   =   3*3600;    -- East Africa Time
95         ["irst"]  =   3*3600+1800;-- Iran Standard Time
96         ["zp4"]   =   4*3600;    -- USSR Zone 3
97         ["msd"]   =   4*3600;    -- Moscow Daylight Time
98         ["sct"]   =   4*3600;    -- Seychelles Time
99         ["zp5"]   =   5*3600;    -- USSR Zone 4
100         ["azst"]  =   5*3600;    -- Azerbaijan Summer Time
101         ["mvt"]   =   5*3600;    -- Maldives Time
102         ["uzt"]   =   5*3600;    -- Uzbekistan Time
103         ["ist"]   =   5*3600+1800;-- Indian Standard
104         ["zp6"]   =   6*3600;    -- USSR Zone 5
105         ["lkt"]   =   6*3600;    -- Sri Lanka Time
106         ["pkst"]  =   6*3600;    -- Pakistan Summer Time
107         ["yekst"] =   6*3600;    -- Yekaterinburg Summer Time
108         ["wast"]  =   7*3600;    -- West Australian Standard
109         ["ict"]   =   7*3600;    -- Indochina Time
110         ["wit"]   =   7*3600;    -- Western Indonesia Time
111         ["cct"]   =   8*3600;    -- China Coast; USSR Zone 7
112         ["wst"]   =   8*3600;    -- West Australian Standard
113         ["hkt"]   =   8*3600;    -- Hong Kong
114         ["bnt"]   =   8*3600;    -- Brunei Darussalam Time
115         ["cit"]   =   8*3600;    -- Central Indonesia Time
116         ["myt"]   =   8*3600;    -- Malaysia Time
117         ["pht"]   =   8*3600;    -- Philippines Time
118         ["sgt"]   =   8*3600;    -- Singapore Time
119         ["jst"]   =   9*3600;    -- Japan Standard; USSR Zone 8
120         ["kst"]   =   9*3600;    -- Korean Standard
121         ["east"]  =  10*3600;    -- Eastern Australian Standard
122         ["gst"]   =  10*3600;    -- Guam Standard; USSR Zone 9
123         ["nct"]   =  11*3600;    -- New Caledonia Time
124         ["nzt"]   =  12*3600;    -- New Zealand
125         ["nzst"]  =  12*3600;    -- New Zealand Standard
126         ["fjt"]   =  12*3600;    -- Fiji Time
127         ["idle"]  =  12*3600;    -- International Date Line East
128 }
129
130
131 -- Find corresponding timezone offset
132 function tz_offset(tz)
133
134         if type(tz) == "string" then
135
136                 -- check for a numeric identifier
137                 local s, v = tz:match("([%+%-])([0-9]+)")
138                 if s == '+' then s = 1 else s = -1 end
139                 if v then v = tonumber(v) end
140
141                 if s and v then
142                         return s * 60 * ( math.floor( v / 100 ) * 60 + ( v % 100 ) )
143
144                 -- lookup symbolic tz
145                 elseif TZ[tz:lower()] then
146                         return TZ[tz:lower()]
147                 end
148
149         end
150
151         -- bad luck
152         return 0
153 end
154
155 -- Convert a HTTP date to unixtime
156 function to_unix(date)
157
158         if not ucache[date] then
159                 local wd, day, mon, yr, hr, min, sec, tz = date:match(
160                         "([A-Z][a-z][a-z]), ([0-9]+) " ..
161                         "([A-Z][a-z][a-z]) ([0-9]+) " ..
162                         "([0-9]+):([0-9]+):([0-9]+) " ..
163                         "([A-Z0-9%+%-]+)"
164                 )
165
166                 if day and mon and yr and hr and min and sec then
167                         -- find month
168                         local month = 1
169                         for i = 1, 12 do
170                                 if MONTHS[i] == mon then
171                                         month = i
172                                         break
173                                 end
174                         end
175
176                         -- convert to epoch time
177                         ucache[date] = tz_offset(tz) + os.time( {
178                                 year  = yr,
179                                 month = month,
180                                 day   = day,
181                                 hour  = hr,
182                                 min   = min,
183                                 sec   = sec
184                         } )
185                 end
186         end
187
188         return ucache[date] or 0
189 end
190
191 -- Convert a unixtime to HTTP date
192 function to_http(time)
193         if not hcache[time] then
194                 hcache[time] = os.date( "%a, %d %b %Y %H:%M:%S GMT", time )
195         end
196
197         return hcache[time]
198 end
199
200 -- Compare two dates
201 function compare(d1, d2)
202
203         if d1:match("[^0-9]") then d1 = to_unix(d1) end
204         if d2:match("[^0-9]") then d2 = to_unix(d2) end
205
206         if d1 == d2 then
207                 return 0
208         elseif d1 < d2 then
209                 return -1
210         else
211                 return 1
212         end
213 end