在Java中,我想获得格林尼治标准时间的当前时间。
我尝试了各种各样的选项:
Date date = new Date();
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
date1 = calendar.getTime();
但是日期总是在我当地的时区解释。
我做错了什么以及如何将java Date转换为GMT?
答案 0 :(得分:32)
在获得日期时你在后端做了正确的事情,但是没有任何迹象表明你没有按照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的时区。
答案 1 :(得分:18)
我想知道为什么没有人这样做:
Calendar time = Calendar.getInstance();
time.add(Calendar.MILLISECOND, -time.getTimeZone().getOffset(time.getTimeInMillis()));
Date date = time.getTime();
更新: 从Java 8,9,10及更多版本开始,Java应该有更好的替代方案。感谢您对@humanity的评论
答案 2 :(得分:6)
根据我的经验,Java中捆绑的Calendar和Date类可以产生不良效果。
如果您不介意升级到Java 8,请考虑使用ZonedDateTime
ZonedDateTime currentDate = ZonedDateTime.now( ZoneOffset.UTC );
答案 3 :(得分:5)
Instant.now()
建议您使用Java 8及更高版本中内置的java.time框架时,Answer by Damilola是正确的。但是,如果您只想要UTC而不是任何特定的时区,那么该答案会使用ZonedDateTime
类,这是一种过度杀伤力。
麻烦的旧日期时间类现在已经遗留下来,取而代之的是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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 4 :(得分:3)
要获得格林威治标准时间的毫秒时间,您需要的是
long millis = System.currentTimeMillis();
您也可以
long millis = new Date().getTime();
和
long millis =
Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTimeInMillis();
但这些是进行相同呼叫的低效方式。
答案 5 :(得分:2)
在尝试了很多方法后,我发现,为了在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 :(得分:1)
首先,您要问不可能的事情。没有老式的Date
对象,因为不能具有时区或GMT偏移量。
但是日期总是在我的本地时区解释。
我想您已经打印了Date
或做了其他隐式调用它的方法toString
。我相信这是在您的时区中唯一解释Date
的时间。更准确地说,是在JVM的当前默认时区中。另一方面,这是不可避免的。 Date.toString()
确实以这种方式运行,它获取了JVM的时区设置,并将其用于呈现要返回的字符串。
不过,您不应使用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。
答案 7 :(得分:0)
这非常简单直接。
Date date = new Date();
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
Calendar cal = Calendar.getInstance(TimeZone.getDefault());
date = cal.getTime();
现在日期将包含当前的GMT时间。
答案 8 :(得分:0)
有用的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;
}
答案 9 :(得分:0)
在Java 8之后,您可能需要获取如下格式的时间:
DateTimeFormatter.ofPattern("HH:mm:ss.SSS").format(LocalTime.now(ZoneId.of("GMT")));
答案 10 :(得分:0)
以下代码将获得日期减去时区偏移量:
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
我的系统位于格林尼治标准时间+8,所以diffInMillis = 28800000 = 8 * 60 * 60 * 1000
。