【发布时间】:2011-10-20 15:59:32
【问题描述】:
如何解析 Java TDate ?我想将其解析为 java Date 对象。日期值为 2011-11-22T00:00:00-06:00
【问题讨论】:
-
顺便说一句,您从哪里得到术语“TDate”?我以前从未听说过。
-
也许你的意思是 ISO 8601“组合日期和时间”格式en.wikipedia.org/wiki/ISO_8601
如何解析 Java TDate ?我想将其解析为 java Date 对象。日期值为 2011-11-22T00:00:00-06:00
【问题讨论】:
您可以使用SimpleDateFormat:
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
// Set time zone, locale etc
Date date = format.parse(text);
我个人强烈建议您使用 Joda Time 而不是内置的 Java 类型,但这是一个单独的讨论......
【讨论】:
T 需要用单引号括起来'T' 而且你需要一个时区。
java.lang.IllegalArgumentException: Illegal pattern character 'T'
-06:00 ,而是使用最有可能给出错误时间的 JVM 的默认时区。请参阅 Arvind Kumar Avinash 的正确答案。为了您自己,请更喜欢使用 java.time。
java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,改用2014年3月发布的modern Date-Time API*。
java.time 的解决方案:现代日期时间 API 基于 ISO 8601,只要日期时间字符串符合 ISO 8601 标准,就不需要明确使用 DateTimeFormatter 对象。
由于您的日期时间字符串 2011-11-22T00:00:00-06:00 已经符合带有时区偏移的 ISO 8601 日期时间格式,您可以直接将其解析为 OffsetDateTime。
演示:
import java.time.OffsetDateTime;
public class Main {
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.parse("2011-11-22T00:00:00-06:00");
System.out.println(odt);
}
}
输出:
2011-11-22T00:00-06:00
从 Trail: Date Time 了解有关现代日期时间 API 的更多信息。
一些重要说明:
OffsetDateTime 的对象转换为具有不同ZoneOffset 的OffsetDateTime 对象,您可以使用OffsetDateTime#withOffsetSameInstant 来实现,例如OffsetDateTime odtWithOffsetTwoHours = odt.withOffsetSameInstant(ZoneOffset.of("+02:00"));
OffsetDateTime odtInUtc = odt.withOffsetSameInstant(ZoneOffset.UTC);
OffsetDateTime 的对象转换为java.util.Date 的对象,您可以按如下方式进行:Date date = Date.from(odt.toInstant());
正如我已经提到的,您应该尽量避免容易出错的旧版 API。只是为了完整起见,我在下面使用旧版 API 编写了解决方案。
由于您的日期时间字符串的时区偏移量为-06:00,因此解析它的正确格式为
y-M-d'T'H:m:sXXX
请注意,对于解析,单个 y 可以同时满足两位数和四位数的年份表示。同样,单个m 可以同时满足一位数和两位数的月份。其他字段的行为也类似。
演示:
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) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("y-M-d'T'H:m:sXXX", Locale.ENGLISH);
Date date = sdf.parse("2011-11-22T00:00:00-06:00");
// Display in the default format i.e. the value of date#toString
System.out.println(date);
// #################Display in custom format and timezone#################
// At timezone offset of -06:00 hours
sdf.setTimeZone(TimeZone.getTimeZone("GMT-06:00"));
System.out.println(sdf.format(date));
// In UTC
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
System.out.println(sdf.format(date));
// In New York
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println(sdf.format(date));
}
}
输出:
Tue Nov 22 06:00:00 GMT 2011
2011-11-22T0:0:0-06:00
2011-11-22T6:0:0Z
2011-11-22T1:0:0-05:00
注意java.util.Date 对象不是像modern Date-Time types 那样的真实日期时间对象;相反,它表示自称为“纪元”的标准基准时间以来的毫秒数,即January 1, 1970, 00:00:00 GMT(或 UTC)。由于它不包含任何格式和时区信息,因此它应用格式 EEE MMM dd HH:mm:ss z yyyy 和 JVM 的时区来返回从该毫秒值派生的 Date#toString 的值。如果您需要以不同的格式和时区打印日期时间,则需要使用具有所需格式和适用时区的SimpleDateFormat,如上面的代码所示。
* 出于任何原因,如果您必须坚持使用 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。
【讨论】: