java simpledateformat 解析字符串错误
java simpledateformat parse string error
//有我的代码
public static void main(String[] args) {
String a = "19900416000000";
String b = "19900415000000";
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
df.setLenient(false);
try {
df.parse(a);
} catch (ParseException e) {
System.out.println("a parse error");
e.printStackTrace();
}
try {
df.parse(b);
}catch (ParseException e){
System.out.println("b parse error");
e.printStackTrace();
}
// 我得到一个错误,像这样
b parse error
java.text.ParseException: Unparseable date: "19900415000000"
at java.text.DateFormat.parse(DateFormat.java:366)
at org.suanhua.elasticsearch.client.ETLTest.main(ETLTest.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
那么,a 和 b 有什么不同?为什么 parse(b) 会出错?
//有我的import
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
//在intellij下使用jdk8
您的问题似乎与时区有关。
正在我的 jdk1.8 中测试所有时区。0_91 安装。
String a = "19900416000000";
String b = "19900415000000";
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
df.setLenient(false);
for (String id : TimeZone.getAvailableIDs()) {
df.setTimeZone(TimeZone.getTimeZone(id));
try {
df.parse(a);
} catch (ParseException e) {
System.out.println(id + ": " + e);
}
try {
df.parse(b);
} catch (ParseException e) {
System.out.println(id + ": " + e);
}
}
输出
Asia/Chongqing: java.text.ParseException: Unparseable date: "19900415000000"
Asia/Chungking: java.text.ParseException: Unparseable date: "19900415000000"
Asia/Harbin: java.text.ParseException: Unparseable date: "19900415000000"
Asia/Shanghai: java.text.ParseException: Unparseable date: "19900415000000"
PRC: java.text.ParseException: Unparseable date: "19900415000000"
CTT: java.text.ParseException: Unparseable date: "19900415000000"
如果您的默认时区是其中任何一个,那么它将失败,因为 1990 年 4 月 15 日的午夜不存在,因为那是夏令时开始的时间,即午夜,时钟被设置为凌晨 1 点,所以午夜不存在。
.
FWIW,Bowie,你 JDK 8 中较新的日期和时间 类 可以解析字符串并给你例如
1990-04-16T00:00+09:00[Asia/Chongqing]
1990-04-15T01:00+09:00[Asia/Chongqing]
您会注意到第二个字符串在输入字符串中表示 00 的地方有几个小时的 01。我用过(编辑:添加 dtf
的创建):
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
System.out.println(LocalDateTime.parse(b, dtf)
.atZone(ZoneId.of("Asia/Chongqing")));
如果只需要电脑的默认时区,可以使用ZoneId.systemDefault()
。
无论如何,既然您使用的是 JDK 8,那么您是否有充分的理由坚持使用过时的 类 SimpleDateFormat
和朋友?较新的 类 通常更易于使用。
如果你需要赶上夏令时的日期时间,你将不得不特殊处理。例如转换回 LocalDateTime
并查看是否与您解析的相同。
PS 我还有一个观察结果无法令人满意地解释:Andreas 提到的时区之一是 CTT。我认为这是指中国台湾时间,所以我预计它与 Asia/Taipei 相同。但是,当我将后者放入我的代码中时,我得到 1990-04-15T00:00+08:00[Asia/Taipei]
,即 00 小时,所以这里时间 0:00 午夜存在。对于安德烈亚斯提到的其他 5 个时区,我得到 01 小时。
//有我的代码
public static void main(String[] args) {
String a = "19900416000000";
String b = "19900415000000";
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
df.setLenient(false);
try {
df.parse(a);
} catch (ParseException e) {
System.out.println("a parse error");
e.printStackTrace();
}
try {
df.parse(b);
}catch (ParseException e){
System.out.println("b parse error");
e.printStackTrace();
}
// 我得到一个错误,像这样
b parse error
java.text.ParseException: Unparseable date: "19900415000000"
at java.text.DateFormat.parse(DateFormat.java:366)
at org.suanhua.elasticsearch.client.ETLTest.main(ETLTest.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
那么,a 和 b 有什么不同?为什么 parse(b) 会出错?
//有我的import
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
//在intellij下使用jdk8
您的问题似乎与时区有关。
正在我的 jdk1.8 中测试所有时区。0_91 安装。
String a = "19900416000000";
String b = "19900415000000";
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
df.setLenient(false);
for (String id : TimeZone.getAvailableIDs()) {
df.setTimeZone(TimeZone.getTimeZone(id));
try {
df.parse(a);
} catch (ParseException e) {
System.out.println(id + ": " + e);
}
try {
df.parse(b);
} catch (ParseException e) {
System.out.println(id + ": " + e);
}
}
输出
Asia/Chongqing: java.text.ParseException: Unparseable date: "19900415000000"
Asia/Chungking: java.text.ParseException: Unparseable date: "19900415000000"
Asia/Harbin: java.text.ParseException: Unparseable date: "19900415000000"
Asia/Shanghai: java.text.ParseException: Unparseable date: "19900415000000"
PRC: java.text.ParseException: Unparseable date: "19900415000000"
CTT: java.text.ParseException: Unparseable date: "19900415000000"
如果您的默认时区是其中任何一个,那么它将失败,因为 1990 年 4 月 15 日的午夜不存在,因为那是夏令时开始的时间,即午夜,时钟被设置为凌晨 1 点,所以午夜不存在。
FWIW,Bowie,你 JDK 8 中较新的日期和时间 类 可以解析字符串并给你例如
1990-04-16T00:00+09:00[Asia/Chongqing]
1990-04-15T01:00+09:00[Asia/Chongqing]
您会注意到第二个字符串在输入字符串中表示 00 的地方有几个小时的 01。我用过(编辑:添加 dtf
的创建):
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
System.out.println(LocalDateTime.parse(b, dtf)
.atZone(ZoneId.of("Asia/Chongqing")));
如果只需要电脑的默认时区,可以使用ZoneId.systemDefault()
。
无论如何,既然您使用的是 JDK 8,那么您是否有充分的理由坚持使用过时的 类 SimpleDateFormat
和朋友?较新的 类 通常更易于使用。
如果你需要赶上夏令时的日期时间,你将不得不特殊处理。例如转换回 LocalDateTime
并查看是否与您解析的相同。
PS 我还有一个观察结果无法令人满意地解释:Andreas 提到的时区之一是 CTT。我认为这是指中国台湾时间,所以我预计它与 Asia/Taipei 相同。但是,当我将后者放入我的代码中时,我得到 1990-04-15T00:00+08:00[Asia/Taipei]
,即 00 小时,所以这里时间 0:00 午夜存在。对于安德烈亚斯提到的其他 5 个时区,我得到 01 小时。