Java日期和时间

时间:2013-07-20 18:53:19

标签: java unix date time calendar

我正在对在unix框上运行的一些代码进行更改。它根据伦敦的当前日期和时间设置数据库中字段的时间。

我使用的方法如下;

private static Date getCurrentTime() {
    SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd-kk:mm:ss.SSS");
    format.setTimeZone(TimeZone.getTimeZone("Europe/London"));

    Calendar cal = Calendar.getInstance();
    Date currentDate = cal.getTime();

    try {
        return format.parse(format.format(currentDate));
    } catch (ParseException e) {
        log.error("Error occured while parsing date-->" + e.getMessage());
    }
    return new Date();
}

private String getStringFromDate(Date date){
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-kk:mm:ss.SSS");
    return sdf.format(date);
}

当生产unix框上的java应用程序处理消息时(设置为托管它的北美时间),当它插入到数据库中时,它落后一小时(未设置为BST)。

如果我在桌面上的Eclipse中运行相同的代码,我会在数据库中获得正确的时间。

我不确定可能导致此问题的原因,并希望有人可以提供帮助。

由于

编辑***乍一看,甚至unix盒子上的日志文件都落后一小时,所以在此基础上我假设它的unix导致了与我的代码相反的问题。

2 个答案:

答案 0 :(得分:2)

Date实例总是在UTC中(或者,它应该是除非你做错了)。您应该将您的日期存储在UTC中的数据库中,并将它们转换为您向用户呈现时所需的任何时区。其他任何东西都只是在寻找麻烦。

您的代码格式化然后在同一个TimeZone中解析Date实例是没有意义的。

答案 1 :(得分:0)

TL;博士

根据定义,Date(和Instant)始终为UTC。所以不需要时区

Instant.now()  // Capture current moment in UTC.

或者,如果您必须使用麻烦的遗留类Date

java.util.Date.from( Instant.now() )  // Avoid the legacy classes whenever possible. When required, you can convert back-and-forth via new methods added to the old classes as seen here.

始终指定时区

永远不要依赖主机操作系统或JVM的当前默认时区。该默认值超出您的控制范围,可以在运行时随时更改。

相反:

  • 始终使用 java.time 类,而不是代码中看到的麻烦旧的遗留类。
  • 始终将所需/预期时区指定为各种 java.time 方法的可选参数,而不是隐式依赖JVM的当前默认值。

java.time

您似乎试图将当前时刻作为java.util.Date对象。旧版类表示UTC中的值,因此时区无关紧要。

Instant

该课程的现代替代是java.time.InstantInstant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

捕捉当前时刻很简单:Instant.now

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

如果您必须Date与尚未更新为 java.time 的旧代码互操作,请通过调用添加到旧类的新方法进行转换。

java.util.Date javaUtilDate = java.util.Date.from( instant ) ;

无论哪种方式,都要非常清楚DateInstant都代表UTC时间轴上的一个点,始终为UTC。

UTC与伦敦时间

此外,请注意 UTC 伦敦时间,这是一个常见的误解,因为从Royal Observatory, Greenwich的点跟踪了UTC / GMT。实际上,伦敦有offset-from-UTC的异常历史,包括采用Daylight Saving Time (DST)

要获得伦敦时间,请指定ZoneId以获得ZonedDateTime

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "Europe/London" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, same point on the timeline, but viewed with a different wall-clock time used by the people of a particular region (time zone).

通常,最佳做法是使您的服务器保持UTC,并以UTC格式执行业务逻辑,存储和日期时间值的交换。仅在业务逻辑或向用户演示时需要使用分区值,例如伦敦时间。

请注意,在上面的代码中,任何计算机或JVM的当前默认时区都是无关紧要的。默认值的更改不会影响您的代码。

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore