Gurcan
Gurcan

Reputation: 438

Get specific UTC date and Time in Lua

As an illustration, I want to grab the (UTC) +0000 UTC date and time in LUA.

I know there are some answers about this but none of them isn't my answer. The general approach to answering this issue is Find Local Time, then plus or minus the UTC number but I don't know my OS Time Zone because my program cab be run in different locations and I cannot get the timezone from my development environment.

Shortly, How can I get the UTC 0 date and time using LUA functions?

Upvotes: 2

Views: 4363

Answers (2)

Joe
Joe

Reputation: 3620

I calculated the difference in seconds between UTC time and local time. Here's a barebones Time class that applies the shift to store UTC time in from_lua_time. The shift is unapplied by using os.date('!*t', time) which works on UTC time.

-- The number of seconds to add to local time to turn it into UTC time.
-- We need to calculate the shift manually because lua doesn't keep track of
-- timezone information for timestamps. To guarantee reproducible results, the
-- Time class stores epoch nanoseconds in UTC.
-- https://stackoverflow.com/a/43601438/30900
local utc_seconds_shift = (function()
  local ts = os.time()
  local utc_date = os.date('!*t', ts)
  local utc_time = os.time(utc_date)
  local local_date = os.date('*t', ts)
  local local_time = os.time(local_date)
  return local_time - utc_time
end)()

-- Metatable for the Time class.
local Time = {}

-- Private function to create a new time instance with a properly set metatable.
function Time:new()
  local o = {}
  setmetatable(o, self)
  self.__index = self
  self.nanos = 0
  return o
end

-- Parses the Lua timestamp (assuming local time) and optional nanosec time
-- into a Time class.
function from_lua_time(lua_ts)
  -- Clone because os.time mutates the input table.
  local clone = {
    year = lua_ts.year,
    month = lua_ts.month,
    day = lua_ts.day,
    hour = lua_ts.hour,
    min = lua_ts.min,
    sec = lua_ts.sec,
    isdst = lua_ts.isdst,
    wday = lua_ts.wday,
    yday = lua_ts.yday
  }
  local epoch_secs = os.time(clone) + utc_seconds_shift
  local nanos = lua_ts.nanosec or 0
  local t = Time:new()
  local secs = epoch_secs * 1000000000
  t.nanos = secs + nanos
  return t
end

function Time:to_lua_time()
  local t = os.date('!*t', math.floor(self.nanos / 1000000000))
  t.yday, t.wday, t.isdst = nil, nil, nil
  t.nanosec = self.nanos % 1000000000
  return t
end


Upvotes: 0

Mike V.
Mike V.

Reputation: 2215

If you need to generate epg, then:

local timestamp = os.time() 
local dt1 = os.date( "!*t", timestamp )  -- UTC
local dt2 = os.date( "*t" , timestamp )  -- local 

local shift_h  = dt2.hour - dt1.hour +  (dt1.isdst and 1 or 0)    -- +1 hour if daylight saving
local shift_m = 100 * (dt2.min  - dt1.min) / 60  
print( os.date("%Y%m%d%H%M%S ", timestamp) ..  string.format('%+05d' , shift_h*100 + shift_m ))

Upvotes: 2

Related Questions