Java JodaTime - 如何在 UTC 中获取当前时间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27741288/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 04:57:08  来源:igfitidea点击:

JodaTime - how to get current time in UTC

javajodatime

提问by prom85

I want to get the current time in UTC. What I do so far is following (just for testing purposes):

我想以 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());
  • d1is my local time, that's fine
  • d2is my local time + 1, but should be local time - 1...
  • d1这是我的当地时间,没关系
  • d2是我的当地时间 + 1,但应该是当地时间 - 1 ...

My local time zone is UTC+1 (according to the debug output and the list here: https://www.joda.org/joda-time/timezones.html)...

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

How do I correctly convert from one time zone to another (inclusive the millisecond representation)?

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

EDIT

编辑

I need the date/milliseconds... It's NOT about displaying the time correctly....

我需要日期/毫秒...这与正确显示时间无关....

EDIT 2

编辑 2

Now, with the help of a comment and an answer, I tried following:

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

    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());

OUTPUT

输出

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

What I wanted was, that the local date displays 15 o'clock and utc date displays 14 o'clock... For now, this seems to work...

我想要的是,本地日期显示 15 点钟,UTC 日期显示 14 点钟......现在,这似乎有效......

----- EDIT3 - Final solution -----

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

Hopefully, this is a good solution... I think, i respects all tipps i got...

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

    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());

Output:

输出:

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

采纳答案by Jon Skeet

You're making it far more complicated than you need to:

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

DateTime dt = new DateTime(DateTimeZone.UTC);

No conversionrequired at all. If you find you actually need to convert, you can use withZone. I'd suggest you avoidgoing via LocalDateTime, however, as that way you can lose information due to time zone transitions (two different instants can have the same local time in the same time zone, because clocks go back and repeat local time.

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

Having said all of this, for the sake of testability I personally like using a Clockinterface which allows me to get the current time (e.g. as an Instant). You can then use dependency injection to inject a real system clock when running in production, and a fake clock with a preset time for tests. Java 8's java.timepackage has this idea built into it, btw.

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

回答by LONGHORN007

    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() ) 

);

Instead of System.out.println( sdf.format( new Date() ) put your local date

而不是 System.out.println( sdf.format( new Date() ) 把你的本地日期

回答by Greg Kopff

From here: http://www.joda.org/joda-time/userguide.html#Changing_TimeZone

从这里: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"));

The resulting value dtLondon has the same absolute millisecond time, but a different set of field values.

结果值 dtLondon 具有相同的绝对毫秒时间,但一组不同的字段值。

You can substitute `Europe/London' for the timezone you want (UTC). See this list of proper time zone names.

您可以将“欧洲/伦敦”替换为您想要的时区 (UTC)。请参阅此正确时区名称列表

回答by Meno Hochschild

Please try to listen to Jon Skeets good advise and comments. Here an additional explanation. Your edit-2 contains a mistake:

请尽量听取 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();

If you call toDate()on an object nowUTCof type LocalDateTimethen you can get surprises - see javadoc. Joda-Time claims to use the same fieldsin java.util.Dateas in nowUTC. What does this mean? Let's analyze:

如果你调用toDate()一个nowUTC类型的对象,LocalDateTime那么你会得到惊喜 - 请参阅javadoc。Joda-Time 声称使用the same fieldsin java.util.Dateas in nowUTC。这是什么意思?我们来分析一下:

nowUTC.toString()produces 2015-01-02T14:31:38.241That is without timezone (note the missing Z at the end), so it is just a plain local timestamp. By context, we know it was generated in UTC. In your next step however, you convert it to a java.util.Dateusing the mentioned method above. This method combines the local timestamp with the system timezone (Belgrade) PRESERVING the FIELDS, hence CHANGING the instant. So you have finally miscorrected your instant. And your second line is wrong.

nowUTC.toString()产生2015-01-02T14:31:38.241那是没有时区的(注意最后缺少的 Z),所以它只是一个普通的本地时间戳。根据上下文,我们知道它是在 UTC 中生成的。但是,在下一步中,您将java.util.Date使用上述方法将其转换为 a 。此方法将本地时间戳与系统时区(贝尔格莱德)相结合,保留字段,从而更改瞬间。所以你终于错误地纠正了你的瞬间。你的第二行是错误的。

If you just want

如果你只是想要

utc date displays 14 o'clock

UTC 日期显示 14 点钟

then don't use the questionable and misleading conversion method Joda-Time offers. Use instead a dedicated formatter with the pattern "EEE MMM dd HH:mm:ss zzz yyyy" or similar (Joda-Time offers DateTimeFormatter). Set the UTC-offset on this formatter and print. Done. Abandon completely any call of java.util.Date.toString(). This way, you don't even need to do any dangerous conversion at all.

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

回答by Kobynet

You can also use the static method nowwhich makes it even more readable

您也可以使用静态方法现在这使得它更可读

DateTime.now(DateTimeZone.UTC)

回答by Naidu

Use this

用这个

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

and if you want to format, you can use

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

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

回答by Wicowyn

I fixed this with this converter

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

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());
    }
}

Dates are stored as UTC and recovered with your current time zone

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