Search code examples
luaformattingstring-formatting

formatting function output similar os.date() in lua


I have a function that get current time and do some calculation that return a table. Something like this:

functuin newtime()
    t1 = os.date("*t")
    -- do some calculation that calculate this variable chha_ye , chha_mo , chha_da
    t={} 
    t["ye"] = chha_ye
    t["mo"] = chha_mo
    t["da"] = chha_da
    return t
end

Now I can get newtime().ye. I need formatting output of this function something similar os.date() for example, if chhaa_ye = 4 and chha_mo = 9 :

newtime("%ye")
4
newtime("%ye - %mo")
4 - 9

Default os.date do this, for example

os.date("%Y")
22
os.date("%Y - %m")
22 - 10

How should I do this?


Solution

  • I will provide an answer based on the comment from Egor, slightly modified to make the answer directly testable in a Lua interpreter. First, the os.date function from Lua is quite handy, it returns a hashtable with the corresponding field/values:

    if format is the string "*t", then date returns a table with the following fields: year, month (1–12), day (1–31), hour (0–23), min (0–59), sec (0–61, due to leap seconds), wday (weekday, 1–7, Sunday is 1), yday (day of the year, 1–366), and isdst (daylight saving flag, a boolean). This last field may be absent if the information is not available.

    We could test the function with the following code snippet:

    for k,v in pairs(os.date("*t")) do
     print(k,v)
    end
    

    This will print the following:

    month   10
    year    2022
    yday    290
    day     17
    wday    2
    isdst   false
    sec     48
    min     34
    hour    9
    

    The gsub function, intended for string substitutions, is not limited to a single string, but could take a table as argument.

    string.gsub (s, pattern, repl [, n])

    If repl is a table, then the table is queried for every match, using the first capture as the key.

    function my_stringformat (format)
      local date_fields = os.date("*t")
      local date_string = format:gsub("%%(%a+)", date_fields)
      return date_string
    end
    

    The function can be used as most would expect:

    > my_stringformat("%year - %month")
    2022 - 10
    

    Obviously, it's trivial to rename or add the fields names:

    function my_stringformat_2 (format)
      local date_fields = os.date("*t")
      -- Rename the fields with shorter name
      date_fields.ye = date_fields.year
      date_fields.mo = date_fields.month
      -- Delete previous field names
      date_fields.year  = nil
      date_fields.month = nil
      -- Interpolate the strings
      local date_string = format:gsub("%%(%a+)", date_fields)
      -- return the new string
      return date_string
    end
    

    And the behavior is the same as the previous one:

    > my_stringformat_2("%ye - %mo")
    2022 - 10