JodaTime - 如何获得UTC的当前时间

时间:2015-01-02 11:18:59

标签: java jodatime

我想以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点,而utc日期显示14点... 现在,这似乎有用......

----- EDIT3 - 最终解决方案-----

希望这是一个很好的解决方案......我想,我尊重所有的tipps ......

    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

7 个答案:

答案 0 :(得分:68)

你使它变得比你需要的复杂得多:

DateTime dt = new DateTime(DateTimeZone.UTC);

根本不需要转换。如果您发现确实需要转换,则可以使用withZone。我建议您避免通过LocalDateTime,但是,由于时区转换,您可能会丢失信息(两个不同的时刻可以在同一时间内具有相同的本地时间)时区,因为时钟返回并重复当地时间。

说完所有这些之后,为了可测试性,我个人喜欢使用Clock接口来获取当前时间(例如Instant)。然后,您可以使用依赖注入在生产中运行时注入实际系统时钟,并使用具有预设测试时间的假时钟。 Java 8的java.time包已经内置了这个想法,顺便说一句。

答案 1 :(得分:9)

您还可以使用静态方法now,使其更具可读性

DateTime.now(DateTimeZone.UTC)

答案 2 :(得分:7)

使用此

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

如果您想格式化,可以使用

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

答案 3 :(得分: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具有相同的绝对毫秒时间,但是有一组不同的字段值。

您可以将“欧洲/伦敦”替换为您想要的时区(UTC)。请参阅this list of proper time zone names

答案 4 :(得分:2)

请尝试听听Jon Skeets的好建议和意见。这是一个额外的解释。你的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();

如果您在toDate()类型的对象nowUTC上致电LocalDateTime,那么您可能会感到惊讶 - 请参阅javadoc。 Joda-Time声称在the same fieldsjava.util.Date使用nowUTCnowUTC.toString()。这是什么意思?我们来分析一下:

2015-01-02T14:31:38.241生成java.util.Date没有时区(注意末尾缺少的Z),所以它只是一个普通的本地时间戳。根据上下文,我们知道它是以UTC格式生成的。但是,在下一步中,使用上面提到的方法将其转换为DateTimeFormatter。此方法将本地时间戳与系统时区(贝尔格莱德)保存为FIELDS,从而改变瞬间。所以你最终错误地纠正了你的瞬间。你的第二行是错误的。

如果你只是想要

  

utc日期显示14点

然后不要使用Joda-Time提供的有问题和误导性的转换方法。请使用具有“EEE MMM dd HH:mm:ss zzz yyyy”或类似模式的专用格式化程序(Joda-Time提供java.util.Date.toString())。在此格式化程序上设置UTC偏移量并打印。完成。完全放弃{{1}}的任何电话。这样,您根本不需要进行任何危险的转换。

答案 5 :(得分: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())把你的本地日期

答案 6 :(得分: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());
    }
}

日期存储为UTC并使用您当前的时区恢复