Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare dates in Lua

I have a variable with a date table that looks like this

* table:
 [day]
  * number: 15
 [year]
  * number: 2015
 [month]
  * number: 2

How do I get the days between the current date and the date above? Many thanks!

like image 950
LFS Avatar asked Feb 16 '15 21:02

LFS


2 Answers

You can use os.time() to convert your table to seconds and get the current time and then use os.difftime() to compute the difference. see Lua Wiki for more details.

reference = os.time{day=15, year=2015, month=2}
daysfrom = os.difftime(os.time(), reference) / (24 * 60 * 60) -- seconds in a day
wholedays = math.floor(daysfrom)
print(wholedays) -- today it prints "1"

as @barnes53 pointed out could be off by one day for a few seconds so it's not ideal, but it may be good enough for your needs.

like image 174
ryanpattison Avatar answered Sep 23 '22 06:09

ryanpattison


You can use the algorithms gathered here:

chrono-Compatible Low-Level Date Algorithms

The algorithms are shown using C++, but they can be easily implemented in Lua if you like, or you can implement them in C or C++ and then just provide Lua bindings.

The basic idea using these algorithms is to compute a day number for the two dates and then just subtract them to give you the number of days.


--[[
 http://howardhinnant.github.io/date_algorithms.html

 Returns number of days since civil 1970-01-01.  Negative values indicate
    days prior to 1970-01-01.
 Preconditions:  y-m-d represents a date in the civil (Gregorian) calendar
                 m is in [1, 12]
                 d is in [1, last_day_of_month(y, m)]
                 y is "approximately" in
                   [numeric_limits<Int>::min()/366, numeric_limits<Int>::max()/366]
                 Exact range of validity is:
                 [civil_from_days(numeric_limits<Int>::min()),
                  civil_from_days(numeric_limits<Int>::max()-719468)]
]]
function days_from_civil(y, m, d)
    if m <= 2 then
      y = y - 1
      m = m + 9
    else
      m = m - 3
    end
    local era = math.floor(y/400)
    local yoe = y - era * 400                                           -- [0, 399]
    local doy = math.modf((153*m + 2)/5) + d-1                          -- [0, 365]
    local doe = yoe * 365 + math.modf(yoe/4) - math.modf(yoe/100) + doy -- [0, 146096]
    return era * 146097 + doe - 719468
end

local reference_date = {year=2001, month = 1, day = 1}
local date = os.date("*t")

local reference_days = days_from_civil(reference_date.year, reference_date.month, reference_date.day)
local days = days_from_civil(date.year, date.month, date.day)

print(string.format("Today is %d days into the 21st century.",days-reference_days))
like image 20
bames53 Avatar answered Sep 23 '22 06:09

bames53