计算服务器与具有不同时区的客户端之间的时差

时间:2013-11-03 15:30:31

标签: java javascript time

我有一个使用JavaScript运行的客户端应用。以及使用Java运行的服务器应用程序。 当客户端执行某个操作时,我使用Date.getTime()记录完成的时间,然后将其发送回服务器。 在某个地方,我想计算自用户执行该操作到现在已经过了多长时间 - 我想在服务器端进行此计算。

我的问题 - 我在服务器当前时间和动作完成时间之间的差异很大,很大。可能是因为时差。

我希望无论客户端或服务器实际位于何处,这种计算都是正确的。我知道我应该使用GMT / UTC时间,但我找不到正确的方法。

2 个答案:

答案 0 :(得分:1)

正如Pointy所说,信任客户端机器的时钟是不明智的。在你的情况下没有必要。

你的第二句话:

  

当客户端执行某个操作时,我使用Date.getTime()记录完成的时间,然后将其发送回服务器。

......倒退了。服务器端应用程序应该驱动日志记录,并将事实发送给客户端。

在服务器端,在Java中,使用Joda-Time捕获UTC time。将该日期时间保存为数据库的本机日期时间格式或ISO 8601格式化字符串。不建议存储毫秒,因为您需要知道或记录epoch中的毫秒数 - 大多数人都假设是Unix纪元,但并非所有系统和软件都使用它。

在客户端,从服务器向客户端发送一个字符串,用于描述用户本地时区的日期时间。您需要能够获得用户的时区。大多数Web浏览器和Web框架都可以为您提供。

继续阅读本位于美国西雅图的服务器示例,其中一位用户居住在意大利罗马。

服务器端

从您可信赖的时钟获取当前日期时间:服务器计算机的时钟。

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.

org.joda.time.DateTime now = new org.joda.time.DateTime(); // Using host system's clock and default time zone.
org.joda.time.DateTime utc = now.toDateTime( org.joda.time.DateTimeZone.UTC );
System.out.println( "Server's default local time in ISO 8601 format: " + now );
System.out.println( "UTC (Zulu) time zone: " + utc );

跑步时......

Server's default local time in ISO 8601 format: 2013-11-08T19:50:56.990-08:00
UTC (Zulu) time zone: 2013-11-09T03:50:56.990Z

客户端

当需要向用户显示该日期时间时,请将其转换为用户的本地时区。

默认情况下,Joda-Time会转换为ISO 8601格式的String。但是您可以使用格式化程序来创建所需的任何字符串。

如果您想将java.util.Date对象传递给您的网络框架,可以convert between Joda-Time and Date

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.

org.joda.time.DateTimeZone romeTimeZone = org.joda.time.DateTimeZone.forID("Europe/Rome");
org.joda.time.DateTime userDateTime = utc.toDateTime( romeTimeZone );
System.out.println( "In User's time zone: " + userDateTime );

跑步时......

In User's time zone: 2013-11-09T04:50:56.990+01:00

关于Joda-Time及相关问题:

    // Joda-Time - The popular alternative to Sun/Oracle's notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
    // http://www.joda.org/joda-time/

    // Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
    // JSR 310 was inspired by Joda-Time but is not directly based on it.
    // http://jcp.org/en/jsr/detail?id=310

    // By default, Joda-Time produces strings in the standard ISO 8601 format.
    // https://en.wikipedia.org/wiki/ISO_8601

    // About Daylight Saving Time (DST): https://en.wikipedia.org/wiki/Daylight_saving_time

    // Time Zone list: http://joda-time.sourceforge.net/timezones.html

提示:时区定义经常变化且不合理。用户的记忆频繁且不合理地改变。如果您的业务在事实上记录用户的感知时间非常重要,那么请完成上面讨论的工作,但记录用户的时区标识符和服务器的时间,如用户所在的时区(你是什么时候)将作为当地时间发送给用户。

答案 1 :(得分:0)

要获得UTC时间,可以使用(Gregorian)Calendar类:

Calendar cal = new GregorianCalendar();
System.out.println("UTC ms from the epoch: " + cal.getTimeInMillis());