在 Java 中获取 GMT 时间
Posted
技术标签:
【中文标题】在 Java 中获取 GMT 时间【英文标题】:Get GMT Time in Java 【发布时间】:2011-07-11 07:11:13 【问题描述】:在 Java 中,我想以 GMT 格式获取当前时间。
我尝试了这样的各种选项:
Date date = new Date();
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
date1 = calendar.getTime();
但日期总是以我的本地时区解释。
我做错了什么,如何将 java Date 转换为 GMT?
【问题讨论】:
System.currentTimeMillis(),或者只是新的 Date()。已经是格林威治标准时间了。 仅供参考,非常麻烦的旧日期时间类,如java.util.Date
、java.util.Calendar
和 java.text.SimpleDateFormat
现在是 legacy,被 Java 8 中内置的 java.time 类所取代,之后。见Tutorial by Oracle。
【参考方案1】:
很有可能您在获取日期时在后端做了正确的事情,但没有任何迹象表明您没有采用 GMT 时间并根据您机器的当前语言环境对其进行格式化。
final Date currentTime = new Date();
final SimpleDateFormat sdf =
new SimpleDateFormat("EEE, MMM d, yyyy hh:mm:ss a z");
// Give it to me in GMT time.
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("GMT time: " + sdf.format(currentTime));
关键是使用你自己的DateFormat,而不是系统提供的。这样您就可以将 DateFormat 的时区设置为您想要的,而不是设置为 Locale 的时区。
【讨论】:
我想要以毫秒为单位的 GMT 日期有什么想法吗??long millis = System.currentTimeMillis();
将返回自 1 January 1970, 00:00:00.000 UTC
以来经过的毫秒数。 UTC 时间是大多数人在说“GMT 时间”时真正想要的时间。 java.util.Date
有一个 getTime()
方法,它对任意 Date
做同样的事情。根据您的需要,您可能需要使用java.util.Calendar
来构造Date
对象,如果是这样,Calendar's
getTime()
方法将返回一个Date
,然后您可以通过getTime()
获得毫秒偏移量。
【参考方案2】:
要获得格林威治标准时间的毫秒时间,您只需要
long millis = System.currentTimeMillis();
你也可以这样做
long millis = new Date().getTime();
和
long millis =
Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTimeInMillis();
但这些都是进行相同调用的低效方式。
【讨论】:
这个答案不正确。尝试从 long millis = Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTimeInMillis(); 打印新的 Date(millis)它仍然给出当前时区时间。 @JavaEnthusiast ideone.com/seLqnz 无论时区如何,它都会在此处提供 GMT 时间。 所有这些都给了我我的本地时区,它不是格林威治标准时间。 @Forseth11 这是不正确的。除非您的系统时钟设置不正确,否则它们都是 GMT。 @PeterLawrey 我的错。我使用本地时区中的日期格式来显示时间。对不起。【参考方案3】:我想知道为什么没有人这样做:
Calendar time = Calendar.getInstance();
time.add(Calendar.MILLISECOND, -time.getTimeZone().getOffset(time.getTimeInMillis()));
Date date = time.getTime();
更新: 由于 Java 8、9、10 及更高版本,Java 应该支持更好的替代方案。感谢您的评论@humanity
【讨论】:
我尝试了几个选项来实现这一点,但只有你的解决方案可以完美运行 这种方法的一个问题是它在时间序列化时不会更改时区。 仅供参考,非常麻烦的旧日期时间类,如java.util.Date
、java.util.Calendar
和 java.text.SimpleDateFormat
现在是 legacy,被 Java 8 中内置的 java.time 类所取代,之后。见Tutorial by Oracle。【参考方案4】:
根据我的经验,Java 中捆绑的 Calendar 和 Date 类会产生不理想的效果。
如果您不介意升级到 Java 8,请考虑使用 ZonedDateTime
像这样:
ZonedDateTime currentDate = ZonedDateTime.now( ZoneOffset.UTC );
【讨论】:
【参考方案5】:在尝试了很多方法后,我发现,要获得 GMT 的毫秒时间,您需要创建两个单独的 SimpleDateFormat
对象,一个用于在 GMT 中格式化,另一个用于解析。
代码如下:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = new Date();
SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dateTime= dateParser.parse(format.format(date));
long gmtMilliSeconds = dateTime.getTime();
这很好用。 :)
【讨论】:
【参考方案6】:这非常简单直接。
Date date = new Date();
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
Calendar cal = Calendar.getInstance(TimeZone.getDefault());
date = cal.getTime();
现在日期将包含当前的 GMT 时间。
【讨论】:
【参考方案7】:tl;博士
Instant.now()
java.time
Answer by Damilola 建议您使用 Java 8 及更高版本中内置的 java.time 框架是正确的。但是该答案使用 ZonedDateTime
类,如果您只想要 UTC 而不是任何特定的时区,那就过分了。
麻烦的旧日期时间类现在是遗留的,被 java.time 类所取代。
Instant
Instant
类表示UTC 中时间轴上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。
简单代码:
Instant instant = Instant.now() ;
instant.toString(): 2016-11-29T23:18:14.604Z
您可以将Instant
视为可以添加时区 (ZoneID
) 以获得ZonedDateTime
的构建块。
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date
、Calendar
和 SimpleDateFormat
。
Joda-Time 项目现在位于maintenance mode,建议迁移到 java.time。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
从哪里获得 java.time 类?
Java SE 8 和 SE 9 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6 和 SE 7 ThreeTen-Backport 中的大部分 java.time 功能都向后移植到 Java 6 和 7。 Android ThreeTenABP 项目专门针对 android 改编 ThreeTen-Backport(如上所述)。 见How to use…。ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval
、YearWeek
、YearQuarter
和more。
【讨论】:
【参考方案8】:以下有用的 Utils 方法可通过 DST 节省来管理 GMT 时间:
public static Date convertToGmt(Date date)
TimeZone tz = TimeZone.getDefault();
Date ret = new Date(date.getTime() - tz.getRawOffset());
// if we are now in DST, back off by the delta. Note that we are checking the GMT date, this is the KEY.
if (tz.inDaylightTime(ret))
Date dstDate = new Date(ret.getTime() - tz.getDSTSavings());
// check to make sure we have not crossed back into standard time
// this happens when we are on the cusp of DST (7pm the day before the change for PDT)
if (tz.inDaylightTime(dstDate))
ret = dstDate;
return ret;
public static Date convertFromGmt(Date date)
TimeZone tz = TimeZone.getDefault();
Date ret = new Date(date.getTime() + tz.getRawOffset());
// if we are now in DST, back off by the delta. Note that we are checking the GMT date, this is the KEY.
if (tz.inDaylightTime(ret))
Date dstDate = new Date(ret.getTime() + tz.getDSTSavings());
// check to make sure we have not crossed back into standard time
// this happens when we are on the cusp of DST (7pm the day before the change for PDT)
if (tz.inDaylightTime(dstDate))
ret = dstDate;
return ret;
【讨论】:
Ajava.util.Date
已采用 UTC。这段代码对我来说毫无意义。【参考方案9】:
在 java 8 之后,你可能希望得到如下格式化的时间:
DateTimeFormatter.ofPattern("HH:mm:ss.SSS").format(LocalTime.now(ZoneId.of("GMT")));
【讨论】:
【参考方案10】:你不能
首先,你问的是不可能的事。一个老式的 Date
对象没有,因为不能有时区或 GMT 偏移量。
但日期总是以我的本地时区解释。
我想你已经打印了Date
或者做了其他隐含地调用它toString
方法的事情。我相信这是 Date
在您的时区中被解释的唯一一次。更准确地说是在您的 JVM 的当前默认时区。另一方面,这是不可避免的。 Date.toString()
确实以这种方式运行,它获取 JVM 的时区设置并使用它来呈现要返回的字符串。
你可以用 java.time
不过,您不应该使用 Date
。该课程设计不佳,幸运的是早已过时。此外,java.time,替代它的现代 Java 日期和时间 API,有一两个类用于日期和时间 与 GMT 或 UTC 的偏移。我现在认为 GMT 和 UTC 是同义词,严格来说它们不是。
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println("Time now in UTC (GMT) is " + now);
刚才运行这个sn-p的时候,输出是:
现在 UTC (GMT) 时间是 2019-06-17T11:51:38.246188Z
输出的尾随 Z
表示 UTC。
链接
Oracle tutorial: Date Time 解释如何使用 java.time。 The Difference Between GMT and UTC 在 timeanddate.com 上。【讨论】:
【参考方案11】:以下代码将得到日期减去时区偏移量:
protected Date toGmt0(ZonedDateTime time)
ZonedDateTime gmt0 = time.minusSeconds(time.getOffset().getTotalSeconds());
return Date.from(gmt0.toInstant());
@Test
public void test()
ZonedDateTime now = ZonedDateTime.now();
Date dateAtSystemZone = Date.from(now.toInstant());
Date dateAtGmt0 = toGmt0(now);
SimpleDateFormat sdfWithoutZone = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
SimpleDateFormat sdfWithZoneGmt0 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ITALIAN);
sdfWithZoneGmt0.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(""
+ "\ndateAtSystemZone = " + dateAtSystemZone
+ "\ndateAtGmt0 = " + dateAtGmt0
+ "\ndiffInMillis = " + (dateAtSystemZone.getTime() - dateAtGmt0.getTime())
+ "\n"
+ "\ndateWithSystemZone.format = " + sdfWithoutZone.format(dateAtSystemZone)
+ "\ndateAtGmt0.format = " + sdfWithoutZone.format(dateAtGmt0)
+ "\n"
+ "\ndateFormatWithGmt0 = " + sdfWithZoneGmt0.format(dateAtSystemZone)
);
输出:
dateAtSystemZone = Thu Apr 23 14:03:36 CST 2020
dateAtGmt0 = Thu Apr 23 06:03:36 CST 2020
diffInMillis = 28800000
dateWithSystemZone.format = 2020-04-23 14:03:36.140
dateAtGmt0.format = 2020-04-23 06:03:36.140
dateFormatWithGmt0 = 2020-04-23 06:03:36.140
我的系统是GMT+8,所以diffInMillis = 28800000 = 8 * 60 * 60 * 1000
。
【讨论】:
错了。从ZonedDateTime
的2020-04-22T00:00+08:00[Asia/Shanghai]
我得到Tue Apr 21 08:00:00 GMT 2020
。这是一天中的同一个小时,但不是同一时间。还有一个老式的 Date
既没有时区偏移也没有时区,所以说它是或不是 GMT 没有任何意义。
虽然这段代码可以回答这个问题,但最好包含一些上下文,解释它是如何工作的以及何时使用它。从长远来看,纯代码的答案没有用处。【参考方案12】:
您可以使用 Java 8 java.time
包来实现它
在 Java 中获取当前 GMT 时间:
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println("Print current time in GMT: "+zonedDateTime); // 2021-08-30T03:58:05.815942377Z
将 java.util.Date 转换为 GMT
// use a formatter
DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss O");
Date date = new Date(); //; java.util.Date object
Instant instant = date.toInstant();
ZonedDateTime zonedDateTime = instant.atZone(ZoneOffset.UTC);
System.out.println("java.util.Date to GMT: "+customFormatter.format(zonedDateTime)); // 08/30/2021 03:58:05 GMT
参考
ZonedDateTime DateTimeFormatter Instant【讨论】:
以上是关于在 Java 中获取 GMT 时间的主要内容,如果未能解决你的问题,请参考以下文章