我在解析以下日期时遇到了一个问题。
08 März 2015 02:15:20
代码
SimpleDateFormat fmt = new SimpleDateFormat("dd MMM yyyy HH:mm:ss", Locale.GERMAN);
fmt.setLenient(false);
try {
System.out.println(fmt.parse("08 März 2015 02:15:20"));
} catch (ParseException e) {
e.printStackTrace();
}
经过一番调查后,我发现由于DST如何工作,我的时区早上2点不存在。一旦时钟到达凌晨1:59,下次更新时间将是凌晨3点。我已经检查过以下日期的情况:
"08 März 2015 01:59:59"
"08 März 2015 03:00:00"
两者都可以正确解析。
我想要的是一个日期对象,它正确地解释了我看到的输入日期:
Mar 8, 2015 at 2:15:20 AM
我该如何做到这一点?
答案 0 :(得分:2)
理想情况下,您使用的解析器允许您解析日期/时间值而不尝试完全应用时区 - java.time.*
和Joda Time允许这样做,IIRC,两者都比java.util.*
更清洁。
但是,如果 使用Date
,并且您不知道原始时区,最安全的方法是使用TimeZone
:
SimpleDateFormat parser = new SimpleDateFormat(
"dd MMM yyyy HH:mm:ss",
Locale.GERMAN);
parser.setLenient(false);
parser.setTimeZone(TimeZone.getTimeZone("UTC"));
因此,它将解析它,就好像它最初是在UTC中一样 - 所以当你想格式化它回到文本时,你需要做同样的事情:
SimpleDateFormat formatter = new SimpleDateFormat(
"EEE d, yyyy at h:mm:ss tt",
Locale.US);
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
String text = formatter.format(date);
答案 1 :(得分:0)
将 TimeZone.getTimeZone("Europe/Berlin")
设置为 fmt
的时区。
演示:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) {
SimpleDateFormat fmt = new SimpleDateFormat("dd MMM yyyy HH:mm:ss", Locale.GERMAN);
fmt.setLenient(false);
fmt.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
try {
Date date = fmt.parse("08 März 2015 02:15:20");
System.out.println(fmt.format(date));
} catch (ParseException e) {
e.printStackTrace();
}
}
}
输出:
08 März 2015 02:15:20
如果您想要带有 AM/PM 标记的输出,该技术将保持不变,但额外的步骤是为输出创建另一个 SimpleDateFormat
实例(因为输出的格式将与输入不同) .
演示:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) {
SimpleDateFormat parser = new SimpleDateFormat("dd MMM yyyy HH:mm:ss", Locale.GERMAN);
parser.setLenient(false);
parser.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
SimpleDateFormat formatter = new SimpleDateFormat("dd MMM yyyy hh:mm:ss a", Locale.GERMAN);
formatter.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
try {
Date date = parser.parse("08 März 2015 02:15:20");
System.out.println(formatter.format(date));
} catch (ParseException e) {
e.printStackTrace();
}
}
}
输出:
08 März 2015 02:15:20 AM
java.util
日期时间 API 及其格式化 API SimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*。
另外,下面引用的是来自 home page of Joda-Time 的通知:
<块引用>请注意,从 Java SE 8 开始,要求用户迁移到 java.time (JSR-310) - JDK 的核心部分,取代了该项目。
使用 java.time
(现代日期时间 API)的解决方案:
与 java.util.Date
不同,import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
DateTimeFormatter parser = DateTimeFormatter.ofPattern("dd MMM uuuu HH:mm:ss", Locale.GERMAN);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMM uuuu hh:mm:ss a", Locale.GERMAN);
LocalDateTime ldt = LocalDateTime.parse("08 März 2015 02:15:20", parser);
System.out.println(parser.format(ldt));
System.out.println(formatter.format(ldt));
}
}
只是对自 UNIX 时代(1970 年 1 月 1 日,格林威治标准时间 00:00:00)以来毫秒数的包装,java.time
types 真正代表日期、时间,日期时间,带和不带时区信息。
08 März 2015 02:15:20
08 März 2015 02:15:20 AM
输出:
between
从 Trail: Date Time 了解有关现代 Date-Time API 的更多信息。
* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。