rev |
line source |
jbe/bsw@0
|
1 local function map_2digit_year(y2)
|
jbe/bsw@0
|
2 local current_year = atom.date:get_current().year
|
jbe/bsw@0
|
3 local guess2 = math.floor(current_year / 100) * 100 + tonumber(y2)
|
jbe/bsw@0
|
4 local guess1 = guess2 - 100
|
jbe/bsw@0
|
5 local guess3 = guess2 + 100
|
jbe/bsw@0
|
6 if guess1 >= current_year - 80 and guess1 <= current_year + 10 then
|
jbe/bsw@0
|
7 return guess1
|
jbe/bsw@0
|
8 elseif guess2 >= current_year - 80 and guess2 <= current_year + 10 then
|
jbe/bsw@0
|
9 return guess2
|
jbe/bsw@0
|
10 elseif guess3 >= current_year - 80 and guess3 <= current_year + 10 then
|
jbe/bsw@0
|
11 return guess3
|
jbe/bsw@0
|
12 end
|
jbe/bsw@0
|
13 end
|
jbe/bsw@0
|
14
|
jbe/bsw@0
|
15 function parse.date(str, dest_type, options)
|
jbe/bsw@0
|
16 if dest_type ~= atom.date then
|
jbe/bsw@0
|
17 error("parse.date(...) can only return dates, but a different destination type than atom.date was given.")
|
jbe/bsw@0
|
18 end
|
jbe/bsw@0
|
19 local date_format = locale.get("date_format")
|
jbe/bsw@0
|
20 if date_format and string.find(date_format, "Y+%-D+%-M+") then
|
jbe/bsw@0
|
21 error("Date format collision with ISO standard.")
|
jbe/bsw@0
|
22 end
|
jbe/bsw@0
|
23 if string.match(str, "^%s*$") then
|
jbe/bsw@0
|
24 return nil
|
jbe/bsw@0
|
25 end
|
jbe/bsw@0
|
26 -- first try ISO format
|
jbe/bsw@0
|
27 local year, month, day = string.match(
|
jbe/bsw@0
|
28 str, "^%s*([0-9][0-9][0-9][0-9])%-([0-9][0-9])%-([0-9][0-9])%s*$"
|
jbe/bsw@0
|
29 )
|
jbe/bsw@0
|
30 if year then
|
jbe/bsw@0
|
31 return atom.date{
|
jbe/bsw@0
|
32 year = tonumber(year),
|
jbe/bsw@0
|
33 month = tonumber(month),
|
jbe/bsw@0
|
34 day = tonumber(day)
|
jbe/bsw@0
|
35 }
|
jbe/bsw@0
|
36 end
|
jbe/bsw@0
|
37 if not date_format then
|
jbe/bsw@0
|
38 return atom.date.invalid
|
jbe/bsw@0
|
39 end
|
jbe/bsw@0
|
40 local format_parts = {}
|
jbe/bsw@0
|
41 local numeric_parts = {}
|
jbe/bsw@0
|
42 for part in string.gmatch(date_format, "[YMD]+") do
|
jbe/bsw@0
|
43 format_parts[#format_parts+1] = part
|
jbe/bsw@0
|
44 end
|
jbe/bsw@0
|
45 for part in string.gmatch(str, "[0-9]+") do
|
jbe/bsw@0
|
46 numeric_parts[#numeric_parts+1] = part
|
jbe/bsw@0
|
47 end
|
jbe/bsw@0
|
48 if #format_parts ~= #numeric_parts then
|
jbe/bsw@0
|
49 return atom.date.invalid
|
jbe/bsw@0
|
50 end
|
jbe/bsw@0
|
51 local year, month, day
|
jbe/bsw@0
|
52 local function process_part(format_part, numeric_part)
|
jbe/bsw@0
|
53 if string.find(format_part, "^Y+$") then
|
jbe/bsw@0
|
54 if #numeric_part == 4 then
|
jbe/bsw@0
|
55 year = tonumber(numeric_part)
|
jbe/bsw@0
|
56 elseif #numeric_part == 2 then
|
jbe/bsw@0
|
57 year = map_2digit_year(numeric_part)
|
jbe/bsw@0
|
58 else
|
jbe/bsw@0
|
59 return atom.date.invalid
|
jbe/bsw@0
|
60 end
|
jbe/bsw@0
|
61 elseif string.find(format_part, "^M+$") then
|
jbe/bsw@0
|
62 month = tonumber(numeric_part)
|
jbe/bsw@0
|
63 elseif string.find(format_part, "^D+$") then
|
jbe/bsw@0
|
64 day = tonumber(numeric_part)
|
jbe/bsw@0
|
65 else
|
jbe/bsw@0
|
66 if not #format_part == #numeric_part then
|
jbe/bsw@0
|
67 return atom.date.invalid
|
jbe/bsw@0
|
68 end
|
jbe/bsw@0
|
69 local year_str = ""
|
jbe/bsw@0
|
70 local month_str = ""
|
jbe/bsw@0
|
71 local day_str = ""
|
jbe/bsw@0
|
72 for i = 1, #format_part do
|
jbe/bsw@0
|
73 local format_char = string.sub(format_part, i, i)
|
jbe/bsw@0
|
74 local number_char = string.sub(numeric_part, i, i)
|
jbe/bsw@0
|
75 if format_char == "Y" then
|
jbe/bsw@0
|
76 year_str = year_str .. number_char
|
jbe/bsw@0
|
77 elseif format_char == "M" then
|
jbe/bsw@0
|
78 month_str = month_str .. number_char
|
jbe/bsw@0
|
79 elseif format_char == "D" then
|
jbe/bsw@0
|
80 day_str = day_str .. number_char
|
jbe/bsw@0
|
81 else
|
jbe/bsw@0
|
82 error("Assertion failed.")
|
jbe/bsw@0
|
83 end
|
jbe/bsw@0
|
84 end
|
jbe/bsw@0
|
85 if #year_str == 2 then
|
jbe/bsw@0
|
86 year = map_2digit_year(year_str)
|
jbe/bsw@0
|
87 else
|
jbe/bsw@0
|
88 year = tonumber(year_str)
|
jbe/bsw@0
|
89 end
|
jbe/bsw@0
|
90 month = tonumber(month_str)
|
jbe/bsw@0
|
91 day = tonumber(day_str)
|
jbe/bsw@0
|
92 end
|
jbe/bsw@0
|
93 end
|
jbe/bsw@0
|
94 for i = 1, #format_parts do
|
jbe/bsw@0
|
95 process_part(format_parts[i], numeric_parts[i])
|
jbe/bsw@0
|
96 end
|
jbe/bsw@0
|
97 if not year or not month or not day then
|
jbe/bsw@0
|
98 error("Date parser did not determine year, month and day. Maybe the 'date_format' locale is erroneous?")
|
jbe/bsw@0
|
99 end
|
jbe/bsw@0
|
100 return atom.date{ year = year, month = month, day = day }
|
jbe/bsw@0
|
101 end
|