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.
1 local strformat = string.format
2 local floor = math.floor
3 local function idiv ( n , d )
8 abday = { "Sun" , "Mon" , "Tue" , "Wed" , "Thu" , "Fri" , "Sat" } ;
9 day = { "Sunday" , "Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" } ;
10 abmon = { "Jan" , "Feb" , "Mar" , "Apr" , "May" , "Jun" , "Jul" , "Aug" , "Sep" , "Oct" , "Nov" , "Dec" } ;
11 mon = { "January" , "February" , "March" , "April" , "May" , "June" ,
12 "July" , "August" , "September" , "October" , "November" , "December" } ;
13 am_pm = { "AM" , "PM" } ;
16 --- ISO-8601 week logic
17 -- ISO 8601 weekday as number with Monday as 1 (1-7)
18 local function iso_8601_weekday ( wday )
25 local iso_8601_week do
26 -- Years that have 53 weeks according to ISO-8601
27 local long_years = { }
29 4, 9, 15, 20, 26, 32, 37, 43, 48, 54, 60, 65, 71, 76, 82,
30 88, 93, 99, 105, 111, 116, 122, 128, 133, 139, 144, 150, 156, 161, 167,
31 172, 178, 184, 189, 195, 201, 207, 212, 218, 224, 229, 235, 240, 246, 252,
32 257, 263, 268, 274, 280, 285, 291, 296, 303, 308, 314, 320, 325, 331, 336,
33 342, 348, 353, 359, 364, 370, 376, 381, 387, 392, 398
35 long_years [ v ] = true
37 local function is_long_year ( year )
38 return long_years [ year % 400 ]
40 function iso_8601_week ( self )
41 local wday = iso_8601_weekday ( self.wday )
42 local n = self.yday - wday
43 local year = self.year
46 if is_long_year ( year ) then
47 return year , 53 , wday
49 return year , 52 , wday
51 elseif n >= 361 and not is_long_year ( year ) then
52 return year + 1 , 1 , wday
54 return year , idiv ( n + 10 , 7 ) , wday
61 function t:a ( locale )
62 return "%s" , locale.abday [ self.wday ]
64 function t:A ( locale )
65 return "%s" , locale.day [ self.wday ]
67 function t:b ( locale )
68 return "%s" , locale.abmon [ self.month ]
70 function t:B ( locale )
71 return "%s" , locale.mon [ self.month ]
73 function t:c ( locale )
74 return "%.3s %.3s%3d %.2d:%.2d:%.2d %d" ,
75 locale.abday [ self.wday ] , locale.abmon [ self.month ] ,
76 self.day , self.hour , self.min , self.sec , self.year
80 return "%02d" , idiv ( self.year , 100 )
83 return "%02d" , self.day
85 -- Short MM/DD/YY date, equivalent to %m/%d/%y
87 return "%02d/%02d/%02d" , self.month , self.day , self.year % 100
90 return "%2d" , self.day
92 -- Short YYYY-MM-DD date, equivalent to %Y-%m-%d
94 return "%d-%02d-%02d" , self.year , self.month , self.day
96 -- Week-based year, last two digits (00-99)
98 return "%02d" , iso_8601_week ( self ) % 100
102 return "%d" , iso_8601_week ( self )
106 return "%02d" , self.hour
109 return "%02d" , (self.hour-1) % 12 + 1
112 return "%03d" , self.yday
115 return "%02d" , self.month
118 return "%02d" , self.min
120 -- New-line character ('\n')
121 function t:n ( ) -- luacheck: ignore 212
124 function t:p ( locale )
125 return self.hour < 12 and locale.am_pm[1] or locale.am_pm[2]
127 -- TODO: should respect locale
128 function t:r ( locale )
129 return "%02d:%02d:%02d %s" ,
130 (self.hour-1) % 12 + 1 , self.min , self.sec ,
131 self.hour < 12 and locale.am_pm[1] or locale.am_pm[2]
133 -- 24-hour HH:MM time, equivalent to %H:%M
135 return "%02d:%02d" , self.hour , self.min
138 return "%d" , self:timestamp ( )
141 return "%02d" , self.sec
143 -- Horizontal-tab character ('\t')
144 function t:t ( ) -- luacheck: ignore 212
147 -- ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
149 return "%02d:%02d:%02d" , self.hour , self.min , self.sec
152 return "%d" , iso_8601_weekday ( self.wday )
154 -- Week number with the first Sunday as the first day of week one (00-53)
156 return "%02d" , idiv ( self.yday - self.wday + 7 , 7 )
158 -- ISO 8601 week number (00-53)
160 return "%02d" , select ( 2 , iso_8601_week ( self ) )
162 -- Weekday as a decimal number with Sunday as 0 (0-6)
164 return "%d" , self.wday - 1
166 -- Week number with the first Monday as the first day of week one (00-53)
168 return "%02d" , idiv ( self.yday - iso_8601_weekday ( self.wday ) + 7 , 7 )
170 -- TODO make t.x and t.X respect locale
174 return "%02d" , self.year % 100
177 return "%d" , self.year
180 function t:z ( ) -- luacheck: ignore 212
183 function t:Z ( ) -- luacheck: ignore 212
186 -- A literal '%' character.
187 t["%"] = function ( self ) -- luacheck: ignore 212
191 local function strftime ( format_string , timetable )
192 return ( string.gsub ( format_string , "%%([EO]?)(.)" , function ( locale_modifier , specifier )
193 local func = t [ specifier ]
195 return strformat ( func ( timetable , c_locale ) )
197 error ( "invalid conversation specifier '%"..locale_modifier..specifier.."'" , 3 )
202 local function asctime ( timetable )
203 -- Equivalent to the format string "%c\n"
204 return strformat ( t.c ( timetable , c_locale ) ) .. "\n"
208 strftime = strftime ;