Why is the ColdFusion epoch time one hour behind the javascript epoch time?
Asked Answered
H

3

14

I am writing an application where I need to get the epoch time on the server side using ColdFusion 8 running on Windows Server 2008 and client side using javascript (testing in Google Chrome). The problem is that the epoch time generated by ColdFusion is one hour behind the one generated by javascript. I have verified that the date/time settings are correct both client side and server side.

This is how I am setting the time stamp with ColdFusion:

<cfset cfEpoch = DateDiff("s", "January 1 1970 00:00", DateConvert("Local2utc", now()))>

And this is how I'm setting it with javascript:

var jsEpoch = Math.round(new Date().getTime()/1000.0);

The javascript epoch matches the one on this website (http://www.epochconverter.com/) which makes sense because they're using the same method I'm using. The ColdFusion epoch is one hour behind. Here's what I've run to try to sort this out:

<cfset localDate = now()>
<cfset utcDate = DateConvert("Local2utc", localDate)>
<cfset epoch = DateDiff("s", "January 1 1970 00:00", utcDate)>

<cfoutput>
    Local Date: #localDate# <br>
    UTC Date: #utcDate# <br>
    Epoch: #epoch#
</cfoutput>

That code outputs:

Local Date: {ts '2013-04-30 17:44:56'} 
UTC Date: {ts '2013-04-30 21:44:56'} 
Epoch: 1367354696

So I'm at a loss. Both the local date and UTC date values are correct. It appears that the only explanation is that the DateDiff() function isn't working properly, but I've tested it with other dates and it seems to work fine. I suppose I can just add 3600 to the epoch value it generates but I'd rather not do that without knowing why I'm getting an incorrect value in the first place. Does anyone see what I'm missing here?

Hus answered 30/4, 2013 at 21:57 Comment(1)
What's your JVM version? And what TZ are you in?Sachsen
T
10

Writing a little script you might notice something very strange.

This is what it output for me.

  • 1367360584 - Javascript time
  • 1367360594 - Epoch seconds (convert Epoch to local time)
  • 1367356994 - Epoch seconds (convert local time to UTC)

So converting epoch to local time is spot on, but the other way around isn't. This is running on CF8 too, so if you convert Epoch to local time, it seems to do it right.

Try it out.

<script>
var jsEpoch = Math.round(new Date().getTime()/1000.0);
document.write(jsEpoch + ' - Javascript time <br>');
</script>


<cfset TheDate = now()>
<cfoutput>
#DateDiff("s",DateConvert("utc2Local", "January 1 1970 00:00"), TheDate)# - Epoch seconds (convert Epoch to local time)<br>
#DateDiff("s", "January 1 1970 00:00", DateConvert("Local2utc", TheDate))# - Epoch seconds (convert local time to UTC)
</cfoutput>
Turgeon answered 30/4, 2013 at 22:24 Comment(1)
Gavin is right. This is definitely the way to go. You can easily create a reusable function with a single line: function getEpoch(){return dateDiff('s', dateConvert('utc2Local', createDateTime(1970, 1, 1, 0, 0, 0)), now());}Stingo
S
3

ColdFusion 8 is pretty old, so you should check your JVM version. You may be running an outdated version that doesn't account for the new DST rules. See this Adobe forum for more:

"The US day light savings rules changed since that Version of ColdFusion and it's underlining JRE where released. You need to update the JRE to at least 1.6.12 to get the new rules."

UPDATED:

After further testing, the JVM is not the issue. I get the same results as above on CF9, and we're already past the time frame where the old rules and new rules would return different results.

However, here are a couple ways you could get the correct result (thanks to Gavin's answer):

function getEpoch(date localDate=now()){
    return dateDiff('s', dateConvert('utc2Local', createDateTime(1970, 1, 1, 0, 0, 0)), localDate);
}

Or, you can access the underlying Java method (wrap the result in int() to drop the decimal):

int(createObject('java', 'java.lang.System').currentTimeMillis()/1000);
Stingo answered 30/4, 2013 at 22:8 Comment(0)
M
0

This is timezone hell. Unix time should be seconds from 1970 in UTC time. But they way Coldfusion and railo do it you need to add seconds from Server time not utc. Convert 1970 to "localServer time" then add seconds then convert back to UTC. It seems that when converting to UTC it just shifts the hour and does not apply UTC DST rules. This is correct:

UTC from UNIX:

CreateODBCDateTime(DateConvert("local2Utc", DateAdd("s", #UNIXTIME#, DateConvert("utc2Local", "January 1 1970 00:00"))) )

UNIX FROM no server local time:

DateDiff("s",DateConvert("utc2Local", "January 1 1970 00:00"), dateAdd('h',-timezone_hours_local_to_server, #LOCALTIME#))
Maturity answered 12/9, 2017 at 18:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.