我正在尝试使用Joda在一个简单的Java程序中获取UTC TimeStamp:
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());
}
该计划的输出如下:
UTC Time:1378265162047
UTC Time:2013-09-03 23:26:02.047
毫秒值是正确的UTC时间(即使用GMT-4
时区确认)
第二个值是EST
时区。
我需要的是UTC值不变为java.sql.Timestamp
(即TZ独立),
用于数据库写入。这可能吗?
DateTime srcDateTime = date.toDateTime(srcTZ);
DateTime dstDateTime = srcDateTime.toDateTime(dstTZ);
System.out.println("UTC Time:" + dstDateTime.getMillis());
我知道srcDateTime
是本地日期(GMT-4),而dstDateTime
是。{1}}
UTC(GMT-0)。日期的输出值如下:
Source Date:2013-09-04T09:10:43.683-04:00
Destination Date: 2013-09-04T13:10:43.683Z
我尝试了所有组合,尝试将dstDateTime
的UTC值作为java.sql.TimeStamp:
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()));
用于测试的打印输出:
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
第一个打印行是正确的UTC时间戳。我所需要的只是同样的价值 作为类型java.sql.TimeStamp。我尝试的任何东西总是返回当地的日期时间 机器。
我尝试了以下内容:
System.out.println("UTC Timestamp:" + date.toDateTime(srcTZ).getMillis());
System.out.println("UTC Timestamp:" + new Timestamp(date.toDateTime(srcTZ).getMillis()));
输出如下:
UTC Time:1378342856315 - Correct UTC Time
UTC Timestap:2013-09-04 21:00:56.315 - Local Time other than the expected UTC Time
每当我尝试转换为TimeStamp时,我都会丢失我所追求的有效UTC值。
就方法的参数而言:
srcTZ = DateTimeZone.forTimeZone(TimeZone.getTimeZone("America/Montreal")
dstTZ = DateTimeZone.forTimeZone(TimeZone.getTimeZone("Etc/UTC"))
Local l = new Locale("en", "CA")
非常感谢任何帮助。
尼克。
Hello Matt,
非常感谢您的回复。我们得到的结果与您相同。不知道关于印刷等的事情。更具体地说:
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()));
收益输出:
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
当我们意识到数据库存储本地时间而不是UTC时,问题引起了我的注意:
+---------------------+
| effectivedate |
+---------------------+
| 2013-09-05 09:34:11 |
+---------------------+
Mysql时区设置为'-00:00'
mysql> SELECT CURRENT_TIMESTAMP;
+---------------------+
| CURRENT_TIMESTAMP |
+---------------------+
| 2013-09-05 13:48:09 |
+---------------------+
使用eclipse调试器调试应用程序我们意识到本地日期时间(2013-09-05 09:51:38.468)正在传递给DB(无法发布图像,没有足够的点......)。数据类型是直接的TimeStamp,没有字符串操作。也许eclipse调试器也在使用String.println()
函数,不确定..
我非常感谢调试我们的应用程序的所有帮助。不想占用这么多时间(没有双关语)和努力......
亲切的问候,
尼克。
答案 0 :(得分:24)
我希望这可以节省3天的废话。在代码中将默认时区设置为逻辑。使事情变得更加便携,必须设置一个env变量等。你可以通过在代码,构造函数等逻辑上添加以下内容来实现这一点。:
DateTimeZone.setDefault(DateTimeZone.UTC);
你可以打印UTC,连接UTC无论......
答案 1 :(得分:6)
尝试这个简短的程序,它应该说明发生了什么:
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()));
在我的电脑上输出:
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
如您所见,您可以使用.toInstant()
或.toDateTime(DateTimeZone.UTC)
来加速UTC时间。但即使你打电话 ,你也会在致电getMillis()
时获得UTC值。
所以问题不在于JodaTime。问题在于您如何评估结果。
创建java.sql.Timestamp
时,您将在1970年1月1日UTC之后的毫秒内传递。仅当您显示时,它才会将当地时区应用于结果。
假设您将它作为Timestamp
传递给数据库而没有做一些interm字符串表示,那么您应该没问题。只是因为它看起来像是拨打System.out.println
的当地时间,并不意味着它是内部的当地时间。
java.sql.Timestamp
类扩展java.util.Date
- 这是从中获取此行为的地方。
答案 2 :(得分:1)
我挣扎了几个小时,终于找到了解决方案。
我正在使用PlayFramework - 不确定这是否会对任何人有所帮助,但对于我的数据库连接设置我必须使用:
promise
(添加'& serverTimezone = UTC')
答案 3 :(得分:0)
您需要UTC值还是只需使用Timestamp.toString()方法?这将为您提供在SQL语句中使用的格式化时间字符串。
答案 4 :(得分:0)
LocalDateTime
已经排除了时区,这意味着它或者意味着字面意思是用户输入“他们的”时间的本地时间(例如,用于葬礼邀请,这将始终是在当地时间)或者它如果你提前计划,它已经是UTC了。
如果您的date
已经在srcTZ
的{{1}}中,但已加载为DateTimeZone
,那么您应该返回
LocalDateTime
或者,如果您确定new Timestamp(date.toDateTime(srcTZ).toDateTime(DateTimeZone.UTC).getMillis());
已经是UTC,即GMT + 0,那么您可以返回
date
最后,大多数数据库接受时间戳作为ISO格式的字符串,这是默认的new Timestamp(date.toDateTime(DateTimeZone.UTC).getMillis());
输出:
toString