JodaTime - 如何获取当前UTC时间

33

我希望获取当前的UTC时间。目前为止,我所做的是以下内容(仅用于测试):

    DateTime dt = new DateTime();
    DateTimeZone tz = DateTimeZone.getDefault();
    LocalDateTime nowLocal = new LocalDateTime();
    DateTime nowUTC = nowLocal.toDateTime(DateTimeZone.UTC);

    Date d1 = nowLocal.toDate();
    Date d2 = nowUTC.toDate();

    L.d("tz: " + tz.toString());
    L.d("local: " + d1.toString());
    L.d("utc: " + d2.toString());
  • d1是我的本地时间,这很好。
  • d2是我的本地时间加1,但应该是本地时间减1...

我的本地时区是UTC+1(根据调试输出和这里的列表:https://www.joda.org/joda-time/timezones.html)...

如何正确地从一个时区转换到另一个时区(包括毫秒表示)?

编辑

我需要日期/毫秒... 这不是关于正确显示时间的问题....

编辑2

现在,在一条评论和一个答案的帮助下,我尝试了以下操作:

    DateTimeZone tz = DateTimeZone.getDefault();
    DateTime nowLocal = new DateTime();
    LocalDateTime nowUTC = nowLocal.withZone(DateTimeZone.UTC).toLocalDateTime();
    DateTime nowUTC2 = nowLocal.withZone(DateTimeZone.UTC);

    Date dLocal = nowLocal.toDate();
    Date dUTC = nowUTC.toDate();
    Date dUTC2 = nowUTC2.toDate();

    L.d(Temp.class, "------------------------");
    L.d(Temp.class, "tz    : " + tz.toString());
    L.d(Temp.class, "local : " + nowLocal +     " | " + dLocal.toString());
    L.d(Temp.class, "utc   : " + nowUTC +       " | " + dUTC.toString()); // <= WORKING SOLUTION
    L.d(Temp.class, "utc2  : " + nowUTC2 +      " | " + dUTC2.toString());

输出

tz    : Europe/Belgrade
local : 2015-01-02T15:31:38.241+01:00 | Fri Jan 02 15:31:38 MEZ 2015
utc   : 2015-01-02T14:31:38.241 | Fri Jan 02 14:31:38 MEZ 2015
utc2  : 2015-01-02T14:31:38.241Z | Fri Jan 02 15:31:38 MEZ 2015
我想要的是,当地时间显示15点,协调世界时显示14点... 目前看起来似乎可以工作...
----- 编辑3 - 最终解决方案 -----
希望这是一个好的解决方案... 我认为它尊重了我所得到的所有提示...
    DateTimeZone tz = DateTimeZone.getDefault();
    DateTime nowUTC = new DateTime(DateTimeZone.UTC);
    DateTime nowLocal = nowUTC.withZone(tz);

    // This will generate DIFFERENT Dates!!! As I want it!
    Date dLocal = nowLocal.toLocalDateTime().toDate();
    Date dUTC = nowUTC.toLocalDateTime().toDate();

    L.d("tz    : " + tz.toString());
    L.d("local : " + nowLocal +     " | " + dLocal.toString());
    L.d("utc   : " + nowUTC +       " | " + dUTC.toString());

输出:

tz    : Europe/Belgrade
local : 2015-01-03T21:15:35.170+01:00 | Sat Jan 03 21:15:35 MEZ 2015
utc   : 2015-01-03T20:15:35.170Z | Sat Jan 03 20:15:35 MEZ 2015

我认为这应该提供你所寻找的答案 https://dev59.com/Hmgu5IYBdhLWcg3wCCxK. - kentsurrey
7个回答

87

你把它搞得比必要的要复杂了:

DateTime dt = new DateTime(DateTimeZone.UTC);

完全不需要进行任何转换。如果您确实需要进行转换,可以使用withZone。我建议您避免通过LocalDateTime的方式,因为这样可能会由于时区转换而丢失信息(在同一时区中,两个不同的瞬间可以具有相同的本地时间,因为时钟会倒退和重复本地时间)。

话虽如此,出于可测试性的考虑,我个人喜欢使用Clock接口来获取当前时间(例如作为一个Instant)。然后可以使用依赖注入将真实的系统时钟注入到生产运行环境中,并使用预设时间的假时钟进行测试。顺便提一下,Java 8的java.time包已经内置了这个想法。


2
@prom85:这确实很重要,因为你的“测试”是有问题的,可能与你真正想做的事情完全无关。在特定时区中没有java.util.Date的概念。Date类仅存储一个时间点。它不知道你感兴趣的时区。一个“java.util.Date对象代表本地时区当前时间”的概念是不合逻辑的,就像说“我想要一个以十六进制存储我的年龄的int”一样——一个int没有格式,就像一个Date没有时区。 - Jon Skeet
2
@prom85:我不认为你仔细阅读了我的评论。将java.util.Date从一个时区转换为另一个时区的想法是荒谬的,因为java.util.Date没有所谓的时区。不清楚用户上传数据的情况,但你确实需要先理解关于Date没有时区这个核心观点。 - Jon Skeet
1
@prom85:好的,所以你需要将任何输入转换为“Date”,然后就可以了。要获取当前时间,只需使用new Date(),不必担心其他任何事情。仍然不清楚问题在哪里-特别是因为您仍然没有解释“不起作用”是什么意思。正如我之前所说,您应该说明预期输出和实际输出。 - Jon Skeet
2
@prom85:就像我之前所说,你期望对于代表相同时间点的“Date”值获得不同的结果是不可能的。你还在调用“LocalDateTime.toDate”而没有指定时区 - 那真的不是个好主意。但目前还不清楚为什么你的示例代码中没有使用我的答案中的代码,也就是“new DateTime(DateTimeZone.UTC)”。说实话,我不太明白你为什么关心系统本地时区。很抱歉今天无法提供更多帮助,但我认为你需要仔细考虑你的需求。 - Jon Skeet
1
@prom85:这取决于具体情况,但通常情况下,在除向用户显示值之外的所有地方使用UTC是有意义的。无论您使用他们的时区还是某个特定于事件的时区取决于应用程序。 - Jon Skeet
显示剩余12条评论

15

您还可以使用静态方法now,这将使它更易读

DateTime.now(DateTimeZone.UTC)

哇!简单明了。 - NKM

12

使用这个

DateTime.now().withZone(DateTimeZone.UTC)

如果你想进行格式化,你可以使用

DateTime.now().withZone(DateTimeZone.UTC).toString("yyyyMMddHHmmss")

3
请尽量听取Jon Skeet的建议和评论。这里提供额外的解释。您的edit-2中有一个错误:
DateTimeZone tz = DateTimeZone.getDefault();
DateTime nowLocal = new DateTime();
LocalDateTime nowUTC = nowLocal.withZone(DateTimeZone.UTC).toLocalDateTime();
DateTime nowUTC2 = nowLocal.withZone(DateTimeZone.UTC);

Date dLocal = nowLocal.toDate();
Date dUTC = nowUTC.toDate();
Date dUTC2 = nowUTC2.toDate();

如果您在类型为LocalDateTime的对象nowUTC上调用toDate(),则可能会出现意外情况 - 请参见javadoc。 Joda-Time声称使用java.util.Date中与nowUTC相同的字段。这是什么意思?我们来分析一下:
nowUTC.toString()生成2015-01-02T14:31:38.241。这没有时区(请注意末尾缺少Z),因此它只是一个普通的本地时间戳。通过上下文,我们知道它是在UTC中生成的。但是,在下一步中,您将使用上述方法将其转换为java.util.Date。该方法将本地时间戳与系统时区(贝尔格莱德)结合起来,保留字段,从而改变了即时状态。所以你最终误改了你的即时状态。您的第二行是错误的。
如果您只想要utc日期显示14点钟
如果您涉及编程相关内容,请不要使用Joda-Time提供的可疑和误导性转换方法。相反,使用专用格式化程序,例如"EEE MMM dd HH:mm:ss zzz yyyy"或类似格式(Joda-Time提供了DateTimeFormatter)。在此格式化程序上设置UTC偏移量并进行打印。完成。完全放弃调用java.util.Date.toString()。这样,您甚至不需要进行任何危险的转换。

2
从这里开始:http://www.joda.org/joda-time/userguide.html#Changing_TimeZone
// get current moment in default time zone
DateTime dt = new DateTime();
// translate to London local time
DateTime dtLondon = dt.withZone(DateTimeZone.forID("Europe/London"));

生成的值 dtLondon 具有相同的绝对毫秒时间,但具有不同的字段值。

您可以将 `Europe/London' 替换为所需的时区 (UTC)。请参阅此正确时区名称列表


0

我用这个转换器解决了这个问题

public class DateTimeConverter implements AttributeConverter<DateTime, Date> {
    @Override
    public Date convertToDatabaseColumn(DateTime attribute) {
        return attribute == null ? null
                : new Date(attribute
                        .withZone(DateTimeZone.UTC)
                        .withZoneRetainFields(DateTimeZone.getDefault())
                        .getMillis());
    }

    @Override
    public DateTime convertToEntityAttribute(Date dbData) {
        return dbData == null ? null
               : new DateTime(dbData.getTime())
                        .withZoneRetainFields(DateTimeZone.UTC)
                        .withZone(DateTimeZone.getDefault());
    }
}

日期以协调世界时存储,并使用您当前的时区进行恢复


0
    SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
    // or SimpleDateFormat sdf = new SimpleDateFormat( "MM/dd/yyyy KK:mm:ss a Z" );
    sdf.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
    System.out.println( sdf.format( new Date() ) 

);

不要使用 System.out.println( sdf.format( new Date() ),而是使用本地日期


我编辑了我的问题...我需要日期/毫秒...仅正确显示日期是不够的...谢谢 - prom85

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接