在 Java 中,我想在 GMT 中获取当前时间。
我尝试了这样的各种选项:
Date date = new Date();
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
date1 = calendar.getTime();
但是日期总是在我当地的时区解释。
我做错了什么,如何将 java Date 转换为 GMT?
您在获取日期时在后端做了正确的事情,但没有任何迹象表明您没有采用 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 的时区。
我想知道为什么没有人这样做:
Calendar time = Calendar.getInstance();
time.add(Calendar.MILLISECOND, -time.getTimeZone().getOffset(time.getTimeInMillis()));
Date date = time.getTime();
更新:由于 Java 8、9、10 及更高版本,Java 应该支持更好的替代方案。感谢您的评论@humanity
根据我的经验,Java 中捆绑的 Calendar 和 Date 类可能会产生不理想的效果。如果您不介意升级到 Java 8,请考虑使用ZonedDateTime
像这样:
ZonedDateTime currentDate = ZonedDateTime.now( ZoneOffset.UTC );
要获得格林威治标准时间的毫秒时间,您只需要
long millis = System.currentTimeMillis();
你也可以做
long millis = new Date().getTime();
和
long millis =
Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTimeInMillis();
但这些都是进行相同呼叫的低效方式。
在尝试了很多方法后,我发现,要获得 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();
这工作正常。:)
java.time
您可以使用 Java 8包来实现它
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println("Print current time in GMT: "+zonedDateTime); // 2021-08-30T03:58:05.815942377Z
// 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
首先,你在问不可能的事。一个老式的Date
对象没有,因为不能有时区或 GMT 偏移量。
但是日期总是在我当地的时区解释。
我想你已经打印了Date
或做了其他隐含地调用它的toString
方法。我相信这是Date
在您的时区中解释的唯一时间。更准确地说是在您的 JVM 的当前默认时区。另一方面,这是不可避免的。Date.toString()
确实以这种方式运行,它获取 JVM 的时区设置并使用它来呈现要返回的字符串。
但是,您不应该使用 a 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);
当我刚才运行这个片段时,输出是:
现在 UTC (GMT) 的时间是 2019-06-17T11:51:38.246188Z
输出的尾随Z
表示 UTC。
在 java 8 之后,您可能希望获得如下格式化时间:
DateTimeFormatter.ofPattern("HH:mm:ss.SSS").format(LocalTime.now(ZoneId.of("GMT")));
这非常简单直接。
Date date = new Date();
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
Calendar cal = Calendar.getInstance(TimeZone.getDefault());
date = cal.getTime();
现在日期将包含当前的 GMT 时间。
以下代码将获得日期减去时区偏移量:
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
。</p>
以下有用的 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;
}