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