Ach*_*how 53 java date gmt simpledateformat
码:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(new Date());
try {
String d = sdf.format(new Date());
System.out.println(d);
System.out.println(sdf.parse(d));
} catch (Exception e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
Run Code Online (Sandbox Code Playgroud)
输出:
Thu Aug 08 17:26:32 GMT+08:00 2013
2013.08.08 09:26:32 GMT
Thu Aug 08 17:26:32 GMT+08:00 2013
Run Code Online (Sandbox Code Playgroud)
请注意,format()
格式Date
正确格式为GMT,但parse()
丢失了GMT详细信息.我知道我可以使用substring()
并解决这个问题,但这种现象背后的原因是什么?
这是一个重复的问题,没有任何答案.
编辑:让我以另一种方式提出问题,检索Date对象的方式是什么,以便它始终在GMT中?
Ach*_*how 53
我只需要这样:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat sdfLocal = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
try {
String d = sdf.format(new Date());
System.out.println(d);
System.out.println(sdfLocal.parse(d));
} catch (Exception e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
Run Code Online (Sandbox Code Playgroud)
输出:略显可疑,但我只希望日期保持一致
2013.08.08 11:01:08
Thu Aug 08 11:01:08 GMT+08:00 2013
Run Code Online (Sandbox Code Playgroud)
正如他所说,OP对他的问题的解决方案具有可疑的输出.该代码仍然显示出对时间表示的混淆.为了消除这种混乱,并制作不会导致错误时间的代码,请考虑他所做的扩展:
public static void _testDateFormatting() {
SimpleDateFormat sdfGMT1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdfGMT1.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat sdfGMT2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
sdfGMT2.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat sdfLocal1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
SimpleDateFormat sdfLocal2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
try {
Date d = new Date();
String s1 = d.toString();
String s2 = sdfLocal1.format(d);
// Store s3 or s4 in database.
String s3 = sdfGMT1.format(d);
String s4 = sdfGMT2.format(d);
// Retrieve s3 or s4 from database, using LOCAL sdf.
String s5 = sdfLocal1.parse(s3).toString();
//EXCEPTION String s6 = sdfLocal2.parse(s3).toString();
String s7 = sdfLocal1.parse(s4).toString();
String s8 = sdfLocal2.parse(s4).toString();
// Retrieve s3 from database, using GMT sdf.
// Note that this is the SAME sdf that created s3.
Date d2 = sdfGMT1.parse(s3);
String s9 = d2.toString();
String s10 = sdfGMT1.format(d2);
String s11 = sdfLocal2.format(d2);
} catch (Exception e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
检查调试器中的值:
s1 "Mon Sep 07 06:11:53 EDT 2015" (id=831698113128)
s2 "2015.09.07 06:11:53" (id=831698114048)
s3 "2015.09.07 10:11:53" (id=831698114968)
s4 "2015.09.07 10:11:53 GMT+00:00" (id=831698116112)
s5 "Mon Sep 07 10:11:53 EDT 2015" (id=831698116944)
s6 -- omitted, gave parse exception
s7 "Mon Sep 07 10:11:53 EDT 2015" (id=831698118680)
s8 "Mon Sep 07 06:11:53 EDT 2015" (id=831698119584)
s9 "Mon Sep 07 06:11:53 EDT 2015" (id=831698120392)
s10 "2015.09.07 10:11:53" (id=831698121312)
s11 "2015.09.07 06:11:53 EDT" (id=831698122256)
Run Code Online (Sandbox Code Playgroud)
sdf2和sdfLocal2包含时区,因此我们可以看到实际发生的事情.s1和s2是在EDT区域的06:11:53.s3和s4在格林威治标准时间区域的10:11:53 - 相当于原始的EDT时间.想象一下,我们将s3或s4保存在数据库中,我们使用GMT来保持一致性,因此我们可以在世界任何地方都有时间,而不会存储不同的时区.
s5解析GMT时间,但将其视为当地时间.所以它说"10:11:53" - 格林尼治标准时间 - 但认为当地时间是10:11:53 .不好.
s7解析GMT时间,但忽略字符串中的GMT,因此仍将其视为本地时间.
s8有效,因为现在我们在字符串中包含GMT,而本地区域解析器使用它将一个时区转换为另一个时区.
现在假设您不想存储区域,您希望能够解析s3,但将其显示为本地时间.答案是使用与其存储的时区相同的时区进行解析 - 因此请使用与sdfGMT1中创建的相同的sdf.s9,s10和s11都是原始时间的表示.他们都是"正确的".也就是说,d2 == d1.那么这只是你想要如何显示它的问题.如果要显示DB - GMT时间中存储的内容,则需要使用GMT sdf对其进行格式化.这是s10.
所以这是最终解决方案,如果您不想在字符串中明确存储"GMT",并希望以GMT格式显示:
public static void _testDateFormatting() {
SimpleDateFormat sdfGMT1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdfGMT1.setTimeZone(TimeZone.getTimeZone("GMT"));
try {
Date d = new Date();
String s3 = sdfGMT1.format(d);
// Store s3 in DB.
// ...
// Retrieve s3 from database, using GMT sdf.
Date d2 = sdfGMT1.parse(s3);
String s10 = sdfGMT1.format(d2);
} catch (Exception e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
检索Date对象的方式是什么,以便它始终在GMT中?
Instant.now()
Run Code Online (Sandbox Code Playgroud)
您正在使用麻烦的令人困惑的旧日期时间类,现在由java.time类取代.
Instant
= UTC该Instant
级表示时间轴上的时刻UTC,分辨率为纳秒(最多9个(9)小数的位数).
Instant instant = Instant.now() ; // Current moment in UTC.
Run Code Online (Sandbox Code Playgroud)
要将此数据作为文本进行交换,请仅使用标准ISO 8601格式.这些格式设计合理,非常明确,易于通过机器处理,并且易于被人们阅读.
在解析和生成字符串时,java.time类在默认情况下使用标准格式.
String output = instant.toString() ;
Run Code Online (Sandbox Code Playgroud)
2017-01-23T12:34:56.123456789Z
如果您想要查看特定区域的挂钟时间中显示的相同时刻,请应用a ZoneId
来获取a ZonedDateTime
.
指定适当的时区名称,格式continent/region
,如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
.切勿使用3-4字母缩写,例如EST
或IST
因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!).
ZoneId z = ZoneId.of( "Asia/Singapore" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Same simultaneous moment, same point on the timeline.
Run Code Online (Sandbox Code Playgroud)
请在IdeOne.com上查看此代码.
注意八小时的差异,因为Asia/Singapore
当前的时区与UTC的偏移量为+08:00.同一时刻,不同的挂钟时间.
instant.toString():2017-01-23T12:34:56.123456789Z
zdt.toString():2017-01-23T20:34:56.123456789 + 08:00 [亚洲/新加坡]
避免遗留java.util.Date
类.但如果你必须,你可以转换.查看添加到旧类的新方法.
java.util.Date date = Date.from( instant ) ;
Run Code Online (Sandbox Code Playgroud)
......走另一条路......
Instant instant = myJavaUtilDate.toInstant() ;
Run Code Online (Sandbox Code Playgroud)
仅限日期,请使用LocalDate
.
LocalDate ld = zdt.toLocalDate() ;
Run Code Online (Sandbox Code Playgroud)
该java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如java.util.Date
,Calendar
,和SimpleDateFormat
.
现在处于维护模式的Joda-Time项目建议迁移到java.time类.
要了解更多信息,请参阅Oracle教程.并搜索Stack Overflow以获取许多示例和解释.规范是JSR 310.
从哪里获取java.time类?
该ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval
,YearWeek
,YearQuarter
,和更多.
归档时间: |
|
查看次数: |
91106 次 |
最近记录: |