如何在Java中获取当前的UTC或GMT日期和时间?
如何在Java中获取当前的UTC或GMT日期和时间?
在Java中,java.util.Date没有特定的时区,尽管它的值通常被认为与UTC有关。那么为什么你认为它是在本地时区呢?
要确切:java.util.Date中的值是自Unix纪元以来的毫秒数,Unix纪元发生在1970年1月1日午夜,UTC时间。相同的纪元也可以用其他时区描述,但传统的描述是以UTC为基准的。由于它是自固定纪元以来的毫秒数,所以java.util.Date中的值在世界各地的任何特定时刻都是相同的,不受本地时区的影响。
我怀疑问题在于你通过一个使用本地时区的Calendar实例显示它,或者可能是使用Date.toString()方法,该方法也使用本地时区,或者是一个默认情况下也使用本地时区的SimpleDateFormat实例。
如果这不是问题,请贴出一些示例代码。
无论如何,我建议你仍然使用Joda-Time,它提供了一个更清晰的API。
我使用了一个新的Date对象并将其插入到一个数据库表中。数据库是MySQL,当我在MySQL中使用UTC_TIMESTAMP()函数时,它工作正常,但是当我插入一个新的Date()值时,它是插入在我的本地时区。
那么那可能是一个驱动程序问题。你可能需要将连接设置为UTC,或者类似的设置。我以前遇到过类似的问题,但问题不在java.util.Date中。
谢谢。你是对的。我查看了mysql的连接属性,但我找不到正确的配置。我问了另一个问题:如何将java.util.Date存储到MySQL时间戳字段中的UTC/GMT时区?如果你能,帮我解决一下。
不幸的是,我不知道 - 我已经很久没有使用过JDBC了,也从未使用过MySQL...
根据stackoverflow.com/questions/4123534/...,MySQL JDBC驱动程序将给定的java.util.Timestamp(或java.util.Date)转换为服务器时区。
猫:你是通过写System.out.println(new Date())来确定的吗?如果是这样,请注意那里使用的是toString()方法...如果不是,请提供更多细节。
Date文档中指出:“尽管Date类旨在反映协调世界时(UTC),但实际上可能并不完全反映这一点,这取决于Java虚拟机的宿主环境。”例如,在我的机器或我的Android手机上,当我初始化一个新的Date对象时,它被设置为GMT而不是UTC。我不会给你投票反对,也许我理解错了。
那只是在谈论系统时钟的精度可能有限。我怀疑你是在指Date.toString()的结果,而这只是一个显示问题。但GMT和UTC实际上是相同的时区。(有一些非常微妙的差异,但在这里我们不需要关心。)
你能否指向一些帮助理解为什么认为Joda-Time提供了一个更清晰的API的资源?
我手头没有资源,但Joda Time支持不可变类型并且有更广泛的类型范围是一个好的开始。Date和Calendar API只是糟糕透顶。
你是说new Date().getTime()将返回UTC毫秒,无论时区如何?是什么让你认为Date是在UTC中?
嗯,文档呢?getTime()的文档说明:“返回自1970年1月1日00:00:00 GMT以来的毫秒数。”
谢谢Jon。如果date.toString()打印“Tue Dec 25 10:00:00 IST 2012”,date.getTime()打印1356409800000;那么date.getTime()是毫秒数中的相同“Tue Dec 25 10:00:00”,还是“Tue Dec 25 04:30:00”(IST-5.30 = GMT)?请帮助我理解。
toString()总是使用默认时区。date.getTime()绝对返回自Unix纪元以来的毫秒数,以UTC为准。最准确的说法是,Date本身根本没有时区 - 它只是时间的一个瞬间,可以被视为多个时区的时间。但是当你创建一个实例时,它不依赖于你的时区。
非常感谢。你能告诉我java.sql.TimeStamp()将如何行为吗?它也没有时区吗?ts.toString()将采用本地时区吗?ts.getTime()将是UTC时间吗?
我们现在远离了原始问题。请提一个新问题,按照tinyurl.com/so-list的指示。
stackoverflow.com/questions/14070572/...
这有点吹毛求疵,但是时间/日期转换对于刚开始了解它们的人来说总是一个让人头疼的问题,所以我想指出这一点。JonSkeet说:“date.getTime() definitely returns milliseconds since the Unix epoch, in UTC”。这里的“in UTC”是多余的。纪元发生在格林威治的午夜(以及其他地方)。在任何给定的时刻,“new Date().getTime()”,在地球上的任何地方,应该给你相同的数字。在这个奇怪的日历转换世界中,这是一个罕见的坚实基础。
实际上,它不是在格林威治午夜发生的,因为当时英国处于UTC+1时区。这只是一段奇怪的历史。但我理解你的观点 - 更好地说“new Date().getTime()返回自Unix纪元以来的毫秒数,这个纪元发生在1970年1月1日午夜,UTC时间”。所以UTC是将纪元固定到特定时间点的一部分,而不是返回结果的一部分。
正确的背景,但这个代码答案在这里stackoverflow.com/a/5236123/1643558使用SDF - UTC时区,使用它来格式化日期。SDF模式 - docs.oracle.com/javase/7/docs/api/java/text/...
你假设OP想要一个字符串。没有迹象表明这是这种情况。
字符串与否 - 那个答案更简洁地说明了这一点。先读你的答案,然后读那个答案,再读你的答案,理解起来更有意义。有些人可以更好地理解带有代码的解释。
Date dt2 = new Date(); System.out.println(" Hr " + dt2.getHours() + ", tz offset :" + dt2.getTimezoneOffset());运行这段代码会显示我本地时区的小时数(UTC时间加5.5小时),时区偏移量为-330,这是正确的本地时间,因为我在印度。所以显然需要更改Date对象的时间才能得到UTC时间。
你有没有阅读过你在那里调用的过时方法的文档?(注意:“根据本地时区解释”。)你关于需要更改Date的内容以获取UTC的结论完全是错误的。
嗯,我需要这个。不想使用Joda。不需要国际化,所以想忽略Date类的弃用注释(它说由于无法国际化而被弃用)。只需要当前的GMT时间。所以使用new GreogorianCalender()还是其他什么?Java 6中有什么选项。顺便感谢你的时间:)
需要这个==需要UTC时间
我建议你提一个新问题,详细说明你的要求,你尝试过什么等等。目前我们不知道你是否真的想要一个文本表示,整数值以便可以测试诸如“现在是八月吗?”等问题。你绝对不应该忽略Date方法的弃用 - 国际化只是其中的一部分,尽管这是它们出现问题的一个表现,但它始终使用系统默认时区。文档非常差 🙁
从stackoverflow.com/questions/20482267/...获得答案,将long转换为毫秒数 - 设置到Calendar中。在问题中,cal.setTimeInMillis(long)。
好吧,我很高兴它对你有帮助,即使你从未真正解释过你的问题...。
我理解OP的问题。说JRE没有时区我认为不准确。它有运行的本地机器的时区。JRE从底层操作系统获取时间,通常设置为本地时区。虽然JRE知道那个时区,但它返回本地操作系统时间给'System.currentTimeMillis()'。文档中写着这样的JRE行为。OP问如何将本地时间转换回UTC。这个类可能对此有帮助。
在Java中如何获取当前的UTC或GMT日期和时间?
问题的原因:
Java的java.util.Date对象没有时区,但是它的toString方法在生成日期时间值的字符串表示时会应用JVM的默认时区。这会给程序员带来困惑,因为Date看起来有时区但实际上没有。
解决方法:
应该避免使用Java中自带的java.util.Date、java.util.Calendar和java.text.SimpleDateFormat类,而是使用以下两个可靠的日期时间库:
- Java 8中的java.time.*包
- Joda-Time
在Java 8中,获取当前的UTC/GMT时间只需要一行代码:
Instant instant = Instant.now();
Instant是java.time的基本构建块,表示UTC时间轴上的一个时刻,以纳秒为分辨率。在Java 8中,当前时刻的分辨率只有毫秒级别,但是Java 9根据主机计算机的时钟硬件的能力,提供了纳秒级的实现。
Instant的toString方法使用特定的ISO 8601格式生成其值的字符串表示。这个格式根据需要输出毫秒、微秒或纳秒的零、三、六或九位数字来表示秒的小数部分。
如果需要更灵活的格式化或其他附加功能,可以应用偏移量为零的UTC本身(ZoneOffset.UTC常量)来获取OffsetDateTime:
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
这个OffsetDateTime对象可以以更灵活的方式进行格式化。
另外,可以使用Joda-Time库来获取当前的UTC/GMT日期和时间。要获取当前的UTC/GMT日期和时间,可以使用以下代码:
System.out.println("UTC/GMT date-time in ISO 8601 format: " + new org.joda.time.DateTime(org.joda.time.DateTimeZone.UTC));
Joda-Time是一个第三方的开源免费库,它在Java 8之前就已经存在,并且在Java 8中的java.time.*类得到了启发。Joda-Time可以在较早的Java版本中使用,并且在Java 8中仍然可以正常工作。
在Java中获取当前的UTC或GMT日期和时间可以使用java.time.*包(Java 8及以上版本)或Joda-Time库。这两个库提供了可靠的日期时间处理功能,避免了使用Java自带的类可能带来的问题。
问题的出现的原因是,用户想要在Java中获取当前的UTC或GMT日期和时间。解决方法是使用SimpleDateFormat类来格式化日期和时间,并设置时区为GMT或UTC。
以下是解决方法的代码示例:
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss"); dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT")); //本地时区 SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss"); //将时间转换为GMT return dateFormatLocal.parse( dateFormatGmt.format(new Date()) );
通过将时区设置为GMT或UTC,我们可以确保获取到的日期和时间是以GMT或UTC为基准的。
在讨论中,某些情况下了为什么在使用dateFormatGmt格式化后,还要使用dateFormatLocal进行解析。这是因为SimpleDateFormat只是用来格式化时间的外观,它并不会改变时间本身。因此,需要将获取到的本地时间转换为GMT或UTC时间,然后再进行解析。
另外,某些情况下了如果设备上的时间设置错误,那么获取到的UTC时间也会是错误的。但是在今天的世界中,大多数设备都连接到互联网,会自动校正时间,所以这种情况并不常见。
还某些情况下了UTC和GMT之间没有时间差异。实际上,GMT是一个时区,而UTC是一个时间标准。尽管它们在现在可能可以互换使用,但在将来,GMT可能会与UTC不同步。
参考资料:[timeanddate.com/time/gmt-utc-time.html](https://www.timeanddate.com/time/gmt-utc-time.html)