It is currently March 29th, 2024, 11:33 am

Filetime <-> Unix Epoch timestamp conversion

Get help with creating, editing & fixing problems with skins
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Filetime <-> Unix Epoch timestamp conversion

Post by raiguard »

I am attempting to convert a Windows timestamp (filetime) into a unix epoch timestamp for use in my SunCalc script. I have the following code:

Code: Select all

function Initialize()

    measure = SKIN:GetMeasure('MeasureLocalTime')

end

function Update()

    -- setup timestamps
    local timestamp = measure:GetValue()
    local localTz = (getTimeOffset() / 3600)
    local tzOffset = -6 -- insert the input's timezone offset here. in the case of a weather skin, this would be the
                        -- timezone offset of the location you are getting the data from

    if tzOffset == localTz then
        tDate = os.date("!*t", timestamp)
    else
        tDate = os.date("!*t", timestamp - getTimeOffset() + (tzOffset * 3600))
    end
    tDate.year = tDate.year - (1970 - 1601)  -- convert Windows timestamp (0 = 1/1/1601) to Unix/Lua timestamp (0 = 1/1/1970)
    timestamp = os.time(tDate)  -- recreate timestamp with new parameters

    return timestamp

end

function getTimeOffset() return (os.time() - os.time(os.date('!*t')) + (os.date('*t')['isdst'] and 3600 or 0)) end
This code is supposed to account for timezones and accurately translate the timestamp. However, no matter what I do, the resulting timestamp is ALWAYS one hour ahead. I am using this website to test the timestamps.

I feel like the solution is super easy and obvious, but I just can't wrap my head around it. Can someone help me?

I also made a simple test skin to ease the testing process (left-click the timestamp to copy it to the clipboard so you can paste it on the website):

Code: Select all

[Rainmeter]
MiddleMouseUpAction=[!Refresh]
AccurateText=1

[Variables]

[MeasureLocalTime]
Measure=Time

[MeasureScript]
Measure=Script
ScriptFile=#@#Timestamp.lua

[MeterTimestamp]
Meter=String
FontSize=12
FontFace=Helvetica
FontColor=230,230,230
SolidColor=15,15,15
Padding=5,5,5,5
Text=[MeasureScript]
DynamicVariables=1
LeftMouseUpAction=[!SetClip "[MeasureScript]"]
ToolTipText=Copy to clipboard
Antialias=1
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
balala
Rainmeter Sage
Posts: 16110
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Filetime <-> Unix Epoch timestamp conversion

Post by balala »

User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: Filetime <-> Unix Epoch timestamp conversion

Post by raiguard »

... it's really that easy? Wow. Thanks. And to think that it was in the snippets this entire time!
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
balala
Rainmeter Sage
Posts: 16110
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Filetime <-> Unix Epoch timestamp conversion

Post by balala »

Can you use it?
In the snippets are a lot of interesting things. It always worth to take a look.
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: Filetime <-> Unix Epoch timestamp conversion

Post by raiguard »

Yeah, I can't believe I didn't know that was there.

I just tried to implement it and it caused all sorts of issues. I need to offset the timestamp by the timezone of the location, and I need to be able to manipulate it using the table that os.date() creates, so I can't just add or subtract it by a hardcoded number. I need to figure out why my existing formulas aren't doing the job.

I expanded the test to include all of the results that I need:

Code: Select all

[Rainmeter]
MiddleMouseUpAction=[!Refresh]
AccurateText=1

[Variables]

[StyleString]
FontSize=12
FontFace=Helvetica
FontColor=230,230,230
SolidColor=30,30,30
Padding=5,1,5,0
X=0
Y=R
W=180
DynamicVariables=1
ToolTipText=Copy to clipboard
Antialias=1

[MeasureLocalTime]
Measure=Time
UpdateDivider=-1

[MeasureScript]
Measure=Script
ScriptFile=#@#Timestamp.lua
UpdateDivider=-1

[MeterTime]
Meter=String
MeterStyle=StyleString
Text=Filetime: [MeasureLocalTime:Timestamp]
LeftMouseUpAction=[!SetClip "[MeasureLocalTime:Timestamp]"]

[MeterTimestamp]
Meter=String
MeterStyle=StyleString
Text=Timestamp: [&MeasureScript:GetData('timestamp')]
LeftMouseUpAction=[!SetClip "[&MeasureScript:GetData('timestamp')]"]

[MeterMDate]
Meter=String
MeterStyle=StyleString
Text=mDate: [&MeasureScript:GetData('mDate')]
LeftMouseUpAction=[!SetClip "[&MeasureScript:GetData('mDate')]"]

[MeterZDate]
Meter=String
MeterStyle=StyleString
Text=zDate: [&MeasureScript:GetData('zDate')]
LeftMouseUpAction=[!SetClip "[&MeasureScript:GetData('zDate')]"]

[MeterYsDate]
Meter=String
MeterStyle=StyleString
Text=ysDate: [&MeasureScript:GetData('ysDate')]
LeftMouseUpAction=[!SetClip "[&MeasureScript:GetData('ysDate')]"]

[MeterTmDate]
Meter=String
MeterStyle=StyleString
Text=tmDate: [&MeasureScript:GetData('tmDate')]
LeftMouseUpAction=[!SetClip "[&MeasureScript:GetData('tmDate')]"]

Code: Select all

function Initialize()

    measure = SKIN:GetMeasure('MeasureLocalTime')
    timestamps = {}

end

function Update()

    -- setup timestamps
    local timestamp = measure:GetValue()
    local localTz = (getTimeOffset() / 3600)
    local tzOffset = -6 -- insert the input's timezone offset here. in the case of a weather skin, this would be the
                        -- timezone offset at the location you are getting the data from

    if tzOffset == localTz then
        tDate = os.date("!*t", timestamp)
    else
        tDate = os.date("!*t", timestamp - getTimeOffset() + (tzOffset * 3600))
    end
    tDate.year = tDate.year - (1970 - 1601)  -- convert Windows timestamp (0 = 1/1/1601) to Unix/Lua timestamp (0 = 1/1/1970)
    timestamp = os.time(tDate)  -- recreate timestamp with new parameters
    mDate = tonumber(tostring(timestamp) .. '000')   -- millisecond date (timestamp with three extra zeroes)
    zDate = tonumber(tostring(os.time{ year = tDate.year, month = tDate.month, day = tDate.day, hour = 0, min = 0, sec = 0 }) .. '000') -- timestamp at current day, 0:00:00 (12:00 AM)
    ysDate = zDate - 86400000  -- timestamp at yesterday, 0:00:00 (12:00 AM)
    tmDate =  zDate + 86400000  -- timestamp at tomorrow, 0:00:00 (12:00 AM)

    timestamps.timestamp = timestamp
    timestamps.mDate = mDate
    timestamps.zDate = zDate
    timestamps.ysDate = ysDate
    timestamps.tmDate = tmDate

end

function GetData(key) return timestamps[key] or '' end

function getTimeOffset() return (os.time() - os.time(os.date('!*t')) + (os.date('*t')['isdst'] and 3600 or 0)) end
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017