正如他所说,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();
}
}
在调试器中检查值:
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)
sdf2 和 sdfLocal2 包括时区,所以我们可以看到真正发生了什么。s1 和 s2 位于美国东部夏令时间 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();
}
}