webmcp
diff framework/env/parse/date.lua @ 0:9fdfb27f8e67
Version 1.0.0
author | jbe/bsw |
---|---|
date | Sun Oct 25 12:00:00 2009 +0100 (2009-10-25) |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/framework/env/parse/date.lua Sun Oct 25 12:00:00 2009 +0100 1.3 @@ -0,0 +1,101 @@ 1.4 +local function map_2digit_year(y2) 1.5 + local current_year = atom.date:get_current().year 1.6 + local guess2 = math.floor(current_year / 100) * 100 + tonumber(y2) 1.7 + local guess1 = guess2 - 100 1.8 + local guess3 = guess2 + 100 1.9 + if guess1 >= current_year - 80 and guess1 <= current_year + 10 then 1.10 + return guess1 1.11 + elseif guess2 >= current_year - 80 and guess2 <= current_year + 10 then 1.12 + return guess2 1.13 + elseif guess3 >= current_year - 80 and guess3 <= current_year + 10 then 1.14 + return guess3 1.15 + end 1.16 +end 1.17 + 1.18 +function parse.date(str, dest_type, options) 1.19 + if dest_type ~= atom.date then 1.20 + error("parse.date(...) can only return dates, but a different destination type than atom.date was given.") 1.21 + end 1.22 + local date_format = locale.get("date_format") 1.23 + if date_format and string.find(date_format, "Y+%-D+%-M+") then 1.24 + error("Date format collision with ISO standard.") 1.25 + end 1.26 + if string.match(str, "^%s*$") then 1.27 + return nil 1.28 + end 1.29 + -- first try ISO format 1.30 + local year, month, day = string.match( 1.31 + str, "^%s*([0-9][0-9][0-9][0-9])%-([0-9][0-9])%-([0-9][0-9])%s*$" 1.32 + ) 1.33 + if year then 1.34 + return atom.date{ 1.35 + year = tonumber(year), 1.36 + month = tonumber(month), 1.37 + day = tonumber(day) 1.38 + } 1.39 + end 1.40 + if not date_format then 1.41 + return atom.date.invalid 1.42 + end 1.43 + local format_parts = {} 1.44 + local numeric_parts = {} 1.45 + for part in string.gmatch(date_format, "[YMD]+") do 1.46 + format_parts[#format_parts+1] = part 1.47 + end 1.48 + for part in string.gmatch(str, "[0-9]+") do 1.49 + numeric_parts[#numeric_parts+1] = part 1.50 + end 1.51 + if #format_parts ~= #numeric_parts then 1.52 + return atom.date.invalid 1.53 + end 1.54 + local year, month, day 1.55 + local function process_part(format_part, numeric_part) 1.56 + if string.find(format_part, "^Y+$") then 1.57 + if #numeric_part == 4 then 1.58 + year = tonumber(numeric_part) 1.59 + elseif #numeric_part == 2 then 1.60 + year = map_2digit_year(numeric_part) 1.61 + else 1.62 + return atom.date.invalid 1.63 + end 1.64 + elseif string.find(format_part, "^M+$") then 1.65 + month = tonumber(numeric_part) 1.66 + elseif string.find(format_part, "^D+$") then 1.67 + day = tonumber(numeric_part) 1.68 + else 1.69 + if not #format_part == #numeric_part then 1.70 + return atom.date.invalid 1.71 + end 1.72 + local year_str = "" 1.73 + local month_str = "" 1.74 + local day_str = "" 1.75 + for i = 1, #format_part do 1.76 + local format_char = string.sub(format_part, i, i) 1.77 + local number_char = string.sub(numeric_part, i, i) 1.78 + if format_char == "Y" then 1.79 + year_str = year_str .. number_char 1.80 + elseif format_char == "M" then 1.81 + month_str = month_str .. number_char 1.82 + elseif format_char == "D" then 1.83 + day_str = day_str .. number_char 1.84 + else 1.85 + error("Assertion failed.") 1.86 + end 1.87 + end 1.88 + if #year_str == 2 then 1.89 + year = map_2digit_year(year_str) 1.90 + else 1.91 + year = tonumber(year_str) 1.92 + end 1.93 + month = tonumber(month_str) 1.94 + day = tonumber(day_str) 1.95 + end 1.96 + end 1.97 + for i = 1, #format_parts do 1.98 + process_part(format_parts[i], numeric_parts[i]) 1.99 + end 1.100 + if not year or not month or not day then 1.101 + error("Date parser did not determine year, month and day. Maybe the 'date_format' locale is erroneous?") 1.102 + end 1.103 + return atom.date{ year = year, month = month, day = day } 1.104 +end