在Lua中比较日期

我有一个包含日期表的变量,看起来像这样:

* 表格:
  [日]
  * 数字:15
 [年份]
  * 数字:2015
 [月份]
  * 数字:2

如何获取当前日期与上面日期之间的天数?非常感谢!

点赞
用户2726734
用户2726734

你可以使用 os.time() 方法将你的表格转换为秒,并获得当前时间,然后使用 os.difftime() 方法来计算时间差。参见 Lua Wiki 获取更多详情。

reference = os.time{day=15, year=2015, month=2}
daysfrom = os.difftime(os.time(), reference) / (24 * 60 * 60) -- 一天中的秒数
wholedays = math.floor(daysfrom)
print(wholedays) -- 今天将打印 "1"

正如 @barnes53 指出的,可能会存在几秒钟的时间差,因此不是最理想的方法,但它可能已经足够满足你的需求。

2015-02-16 23:38:04
用户365496
用户365496

你可以使用这里收集的算法:

chrono-Compatible Low-Level Date Algorithms

这些算法使用 C++ 显示,但是如果需要,你可以轻易地在 Lua 中实现它们,或者你可以在 C 或 C++ 中实现它们,然后仅提供 Lua 绑定。

使用这些算法的基本思路是为两个日期计算一个天数,然后将它们相减以得出天数。


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

 返回自公元 1970 年 1 月 1 日以来的天数。负值表示 1970 年 1 月 1 日之前的天数。
 前提条件:y-m-d 表示公民(格里高利)日历中的日期
          m 在 [1, 12] 范围内
          d 在 [1, last_day_of_month(y, m)] 范围内
          y 大约在 [numeric_limits<Int> :: min() / 366,numeric_limits<Int> :: max() / 366] 范围内
          有效范围的精确范围为:
          [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("今天是 21 世纪的第 %d 天.",days-reference_days))
2015-02-16 23:53:09
用户3735873
用户3735873

os.time(至少在 Windows 下)仅限于 1970 年及以后的年份。例如,如果你需要一个通用的解决方案来查找出生于 1970 年之前的人的天龄,那么这将无法运行。你可以使用儒略日转换,并在两个数字之间做减法(今天的日期和目标日期)。

以下给出了一个示例儒略日功能,可适用于任何公元日期(使用 Lua v5.3,因为涉及到“//”,但你也可以适应早期版本):

local
function div(n,d)
  local a, b = 1, 1
  if n < 0 then a = -1 end
  if d < 0 then b = -1 end
  return a * b * (math.abs(n) // math.abs(d))
end

--------------------------------------------------------------------------------
-- 将 YYMMDD 日期转换为自 1900 年 1 月 1 日以来的儒略日(可能为负数)
--------------------------------------------------------------------------------

function julian(year, month, day)
  local temp

  if (year < 0) or (month < 1) or (month > 12)
                or (day < 1) or (day > 31) then
    return
  end
  temp = div(month - 14, 12)
  return (
         day - 32075 +
         div(1461 * (year + 4800 + temp), 4) +
         div(367 * (month - 2 - temp * 12), 12) -
         div(3 * div(year + 4900 + temp, 100), 4)
         ) - 2415021
end
2015-02-17 00:50:42