Java UTC 时间戳 + Joda 时间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18604989/
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-12 09:26:21  来源:igfitidea点击:

UTC Timestamp + Joda Time

javajodatime

提问by Nick Cameo

I am trying to get the UTC TimeStamp in a simple Java program using Joda:

我正在尝试使用 Joda 在一个简单的 Java 程序中获取 UTC 时间戳:

public Timestamp getCurrentUTC(LocalDateTime date, DateTimeZone srcTZ, DateTimeZone dstTZ, Locale l) {
    DateTime srcDateTime = date.toDateTime(srcTZ);
    DateTime dstDateTime = srcDateTime.toDateTime(dstTZ);

    System.out.println("UTC Time:" + dstDateTime.getMillis());      
    System.out.println("UTC Time:" + new Timestamp(dstDateTime.getMillis()));

    return new Timestamp(dstDateTime.getMillis());
}

The output of the program is as follows:

程序的输出如下:

UTC Time:1378265162047
UTC Time:2013-09-03 23:26:02.047

The millisecond value is the correct UTC time (i.e. confirmed with GMT-4timezone) The second value is the ESTtimezone.

毫秒值是正确的 UTC 时间(即用GMT-4时区确认) 第二个值是EST时区。

What I need is the UTC value unchanged as java.sql.Timestamp(ie TZ independent), for a database write. Is this possible?

我需要的是 UTC 值不变java.sql.Timestamp(即 TZ 独立),用于数据库写入。这可能吗?

Edit 1

编辑 1

DateTime srcDateTime = date.toDateTime(srcTZ);

DateTime dstDateTime = srcDateTime.toDateTime(dstTZ);

System.out.println("UTC Time:" + dstDateTime.getMillis());

I know that srcDateTimeis the local date (GMT-4), and dstDateTimeis UTC (GMT-0). Output values of the dates are as follows:

我知道这srcDateTime是本地日期 (GMT-4),并且dstDateTime是 UTC (GMT-0)。日期的输出值如下:

Source Date:2013-09-04T09:10:43.683-04:00

Destination Date: 2013-09-04T13:10:43.683Z

I tried all the combinations to try to get the UTC value of dstDateTimeas a java.sql.TimeStamp:

我尝试了所有组合来尝试获取dstDateTimejava.sql.TimeStamp的 UTC 值:

System.out.println("UTC Time:" + dstDateTime.getMillis());

System.out.println("UTC Time:" + new Timestamp(srcDateTime.toDateTime(DateTimeZone.UTC).getMillis()));

System.out.println("UTC Time:" + new Timestamp(dstDateTime.toDateTime(DateTimeZone.UTC).getMillis()));

The print output for testing:

用于测试的打印输出:

UTC Time:1378298760226 - Correct UTC

UTC Time:2013-09-04 08:46:00.226 - Incorrect Local Date Time instead of the Expected UTC

UTC Time:2013-09-04 08:46:00.226 - Incorrect Local Date Time instead of the Expected UTC

The first print line is the correct UTC timestamp. All I need is that same value as type java.sql.TimeStamp. Anything I tried always returned the local date time of the machine.

第一个打印行是正确的 UTC 时间戳。我所需要的只是与 java.sql.TimeStamp 类型相同的值。我尝试过的任何事情总是返回机器的本地日期时间。

Edit 2

编辑 2

I tried the following:

我尝试了以下方法:

System.out.println("UTC Timestamp:" + date.toDateTime(srcTZ).getMillis());
System.out.println("UTC Timestamp:" + new Timestamp(date.toDateTime(srcTZ).getMillis()));

The output is as follows:

输出如下:

UTC Time:1378342856315 - Correct UTC Time
UTC Timestap:2013-09-04 21:00:56.315 - Local Time other than the expected UTC Time

Whenever I try to convert to TimeStamp, I loose the valid UTC value that I am after.

每当我尝试转换为 TimeStamp 时,我都会丢失我所追求的有效 UTC 值。

In terms of the method's parameters:

在方法的参数方面:

srcTZ = DateTimeZone.forTimeZone(TimeZone.getTimeZone("America/Montreal")
dstTZ = DateTimeZone.forTimeZone(TimeZone.getTimeZone("Etc/UTC"))
Local l = new Locale("en", "CA")

Any help is greatly appreciated.

任何帮助是极大的赞赏。

Nick.

缺口。

Edit 3

编辑 3

Hello Matt,

你好马特,

Thank you so much for your response. We are getting the same results as you. Did not know the thing about printing etc.. More specifically:

非常感谢你的回复。我们得到了和你一样的结果。不知道有关印刷等的事情。更具体地说:

System.out.println("UTC Timestamp:" + srcDateTime.toDateTime(dstTZ).getMillis());
System.out.println("UTC Timestamp:" + srcDateTime.toDateTime(dstTZ));
System.out.println("UTC Timestamp:" + new Timestamp(srcDateTime.toDateTime(dstTZ).getMillis()));

Yields The Output:

产生输出:

UTC Timestamp:1378389098468 - Correct UTC Timestap (Thu, 05 Sep 2013 13:51:38 GMT)
UTC Timestamp:2013-09-05T13:51:38.468Z - Correct UTC Time
UTC Timestamp:2013-09-05 09:51:38.468 - Local time is printed, UTC is expected

The problem was brought to my attention when we realized that the DB was storing the local time instead of UTC:

当我们意识到数据库存储的是本地时间而不是 UTC 时,这个问题引起了我的注意:

+---------------------+
| effectivedate       |
+---------------------+
| 2013-09-05 09:34:11 |
+---------------------+

The Mysql timezone is set to '-00:00'

Mysql 时区设置为“-00:00”

mysql> SELECT CURRENT_TIMESTAMP;
+---------------------+
| CURRENT_TIMESTAMP   |
+---------------------+
| 2013-09-05 13:48:09 |
+---------------------+

Debugging the application using eclipse debugger we realized that the local date time (2013-09-05 09:51:38.468) was being passed to the DB (Can't post images, not enough points...). The datatype is straight TimeStamp, with no string manipulation. Maybe the eclipse debugger is using String.println()function as well, not sure..

使用 eclipse 调试器调试应用程序时,我们意识到本地日期时间 (2013-09-05 09:51:38.468) 正在传递给 DB(无法发布图像,点数不足...)。数据类型是直接的 TimeStamp,没有字符串操作。也许 eclipse 调试器String.println()也在使用函数,不确定..

I really appreciate all the help debugging our application. Did not want to take up so much time (no pun intended) and effort...

我非常感谢调试我们的应用程序的所有帮助。不想占用这么多时间(没有双关语)和努力......

Kind Regards,

亲切的问候,

Nick.

缺口。

采纳答案by Nick Cameo

I hope this saves someone 3 days of bullshit. Set the default timezone somewhere logical in your code. Makes things more portable that having to set an env variable etc.. You can do this by adding the following somewhere logical to your code, Constructor etc..:

我希望这可以为某人节省 3 天的废话。在代码中的某个逻辑位置设置默认时区。使事情变得更便携,而不必设置 env 变量等。您可以通过将以下内容添加到您的代码、构造函数等的逻辑位置来实现此目的:

DateTimeZone.setDefault(DateTimeZone.UTC);

DateTimeZone.setDefault(DateTimeZone.UTC);

You can print UTC, concatenate UTC whatever...

您可以打印 UTC,连接 UTC 任何...

回答by coderatchet

Do you need the UTC value or can you simply use the Timestamp.toString() method? this will give you a formatted time string for use in SQL statements.

您需要 UTC 值还是可以简单地使用 Timestamp.toString() 方法?这将为您提供用于 SQL 语句的格式化时间字符串。

回答by pickypg

LocalDateTimealready excludes the timezone, which means that it either means literally the local time where the user enters "their" time (e.g., for a funeral invitation, which will always be in the local time) or it is already in UTC if you planned ahead.

LocalDateTime已经排除了时区,这意味着它要么字面意思是用户输入“他们”时间的当地时间(例如,对于葬礼邀请,它将始终在当地时间),或者如果您提前计划,它已经在 UTC .

If your dateis already in the srcTZ's DateTimeZone, but loaded as LocalDateTime, then you should return

如果您date已经在srcTZ's 中DateTimeZone,但加载为LocalDateTime,那么您应该返回

new Timestamp(date.toDateTime(srcTZ).toDateTime(DateTimeZone.UTC).getMillis());

Alternatively, if you are sure that the dateis already in UTC, which is GMT+0, then you can return

或者,如果您确定date已经在 UTC,即 GMT+0,那么您可以返回

new Timestamp(date.toDateTime(DateTimeZone.UTC).getMillis());

Finally, most databases accept the timestamp as an ISO formatted string, which is the default toStringoutput:

最后,大多数数据库接受时间戳作为 ISO 格式的字符串,这是默认toString输出:

date/*.toDateTime(srcTZ)*/.toDateTime(DateTimeZone.UTC).toString()

回答by Matt Johnson-Pint

Try this short program, it should illustrate what is going on:

试试这个简短的程序,它应该说明发生了什么:

LocalDateTime date = LocalDateTime.now();
DateTimeZone tz = DateTimeZone.getDefault();

System.out.println(date);
System.out.println(tz);
System.out.println("-----");
System.out.println(date.toDateTime(tz));
System.out.println(date.toDateTime(tz).toInstant());
System.out.println(date.toDateTime(tz).toDateTime(DateTimeZone.UTC));
System.out.println("-----");
System.out.println(date.toDateTime(tz).getMillis());
System.out.println(date.toDateTime(tz).toInstant().getMillis());
System.out.println(date.toDateTime(tz).toDateTime(DateTimeZone.UTC).getMillis());
System.out.println("-----");
System.out.println(new Timestamp(date.toDateTime(tz).getMillis()));
System.out.println(new Timestamp(date.toDateTime(tz).toInstant().getMillis()));
System.out.println(new Timestamp(date.toDateTime(tz).toDateTime(DateTimeZone.UTC).getMillis()));

On my computer, it outputs:

在我的电脑上,它输出:

2013-09-04T19:08:35.111
America/Phoenix
-----
2013-09-04T19:08:35.111-07:00
2013-09-05T02:08:35.111Z
2013-09-05T02:08:35.111Z
-----
1378346915111
1378346915111
1378346915111
-----
2013-09-04 19:08:35.111
2013-09-04 19:08:35.111
2013-09-04 19:08:35.111

As you can see, you can get to the UTC time with either .toInstant(), or with .toDateTime(DateTimeZone.UTC). But even if you call neitherof these, you will still get the UTC value when you call getMillis().

如您所见,您可以使用.toInstant()、 或来获取 UTC 时间.toDateTime(DateTimeZone.UTC)。但是,即使您不调用两个方法,您在调用getMillis().

So the problem isn't with JodaTime. The problem is in how you are evaluating your results.

所以问题不在于 JodaTime。问题在于您如何评估结果。

When you create a java.sql.Timestamp, you're passing in the milliseconds from 1/1/1970 UTC. It's only when you displayit that it is applying the local time zone to the result.

创建 时java.sql.Timestamp,您传递的是 UTC 时间 1/1/1970 的毫秒数。只有当您显示它时,它才会将本地时区应用于结果。

Assuming you are passing it to a database as a Timestampand not doing some interm string representation, then you should be fine. Just because it looks like the local time when you call System.out.println, doesn't mean that it is a local time internally.

假设您将它作为 a 传递给数据库,Timestamp而不是做一些 interterm 字符串表示,那么您应该没问题。仅仅因为它在您调用时看起来像当地时间System.out.println,并不意味着它在内部是当地时间。

The java.sql.Timestampclass extends java.util.Date- which is where it gets this behavior from.

java.sql.Timestamp类扩展java.util.Date-这是它会从这种行为。

回答by lindamarieb

I struggled with this for hours and finally found a solution.

我为此苦苦挣扎了几个小时,终于找到了解决方案。

I'm using PlayFramework - not sure if this will help anyone, but for my database connection setting I had to use:

我正在使用 PlayFramework - 不确定这是否会对任何人有所帮助,但对于我的数据库连接设置,我必须使用:

db.default.url="jdbc:mysql://localhost/continuum?characterEncoding=UTF-8&serverTimezone=UTC"

(add the '&serverTimezone=UTC')

(添加'&serverTimezone=UTC')