37

我正在一个读取文件和处理数据的项目中工作。在那里我必须处理日期,例如:

  1. 2012-01-10 23:13:26
  2. 2012 年 1 月 13 日

我找到了 Joda 包,这是一个有趣的包,但不知道它是否是最简单的。

我能够将第一个示例解析为 DateTime 对象 (Joda) 正则表达式和字符串操作。(例如:通过用“-”替换空格并将其传递给构造函数。

new DateTime("2012-01-10 23:13:26".replace(' ', '-'))

我想它有效,但问题在于第二种格式。我如何使用这样的输入来提取对象,最好是 Joda 对象。我当然可以编写一个函数来将格式更改为 Joda 支持的格式,但想知道是否还有其他方法(甚至是一些本机 Java 库)可以做到这一点。

如果有什么比 Joda 更好的东西,也请告诉我。

谢谢你。

4

6 回答 6

45

使用 Joda-Time,看看DateTimeFormat;它允许解析您提到的两种日期字符串(以及几乎任何其他任意格式)。如果您的需求更加复杂,请尝试DateTimeFormatterBuilder

解析#1:

DateTimeFormatter f = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTime dateTime = f.parseDateTime("2012-01-10 23:13:26");

编辑:实际上LocalDateTime是没有时区的日期时间更合适的类型:

LocalDateTime dateTime = f.parseLocalDateTime("2012-01-10 23:13:26");

对于#2:

DateTimeFormatter f = DateTimeFormat.forPattern("MMMM dd, yyyy");
LocalDate localDate = f.parseLocalDate("January 13, 2012");

是的,就 Java 日期和时间处理而言,Joda-Time 绝对是最佳选择。:)

大多数人都会同意,Joda 是一个非常用户友好的库。例如,我以前从未使用 Joda 进行过这种解析,但我只花了几分钟就从 API 中弄清楚并编写了它。

更新 (2015)

如果您使用的是Java 8,在大多数情况下,您应该简单地使用java.time而不是 Joda-Time。它包含了几乎所有来自 Joda 的好东西——或它们的等价物。对于那些已经熟悉 Joda API 的人来说,Stephen Colebourne 的Joda-Time 到 java.time 迁移指南会派上用场。

以下是上述示例的 java.time 版本。

解析#1:

DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.from(f.parse("2012-01-10 23:13:26"));

您不能将其解析为 ZonedDateTime 或 OffsetDateTime (它们是 Joda 的 DateTime 的对应物,在我的原始答案中使用),但这有点道理,因为解析的字符串中没有时区信息。

解析#2:

DateTimeFormatter f = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
LocalDate localDate = LocalDate.from(f.parse("January 13, 2012"));

这里 LocalDate 是最适合解析的类型(就像 Joda-Time 一样)。

于 2012-01-13T17:43:06.590 回答
24

SimpleDateFormat 会将日期解析为 Java Date 对象:

http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html

SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); // first example
SimpleDateFormat format2 = new SimpleDateFormat("MMMMM dd,yyyy"); // second example

Date d1 = format1.parse( dateStr1 );
Date d2 = format2.parse( dateStr2 );
于 2012-01-13T17:40:00.880 回答
7

我想 Joda 有一个 Formatter 来为你做这件事。我通过谷歌快速搜索找到了这个:http: //johannburkard.de/blog/programming/java/date-time-parsing-formatting-joda-time.html

DateTimeFormatter parser1 =
    DateTimeFormat.forPattern("dd/MMM/yyyy:HH:mm:ss Z");

DateTimeFormatter parser2 =
    DateTimeFormat.forPattern("yyyy-MM-dd HH:mm");

DateTime time = parser1.parseDateTime("<data>");

用于评估模式的语法可以在X-Zero 的链接中找到。

于 2012-01-13T17:42:52.753 回答
5

JodaTime 在很大程度上被认为是 Java 中日期时间处理的事实标准——他们正在努力将其添加到 Java 库的下一个版本中(嗯,有效地)。

要从字符串中获取 JodaTime 日期,您需要查看DateTimeFormat类。

于 2012-01-13T17:42:10.453 回答
2

最简单的方法是根据您期望的格式正确设置 SimpleDateFormat 并使用其 parse 方法为您提供 Date 对象

于 2012-01-13T17:43:25.083 回答
2

tl;博士

LocalDateTime ldt = LocalDateTime.parse( "2012-01-10 23:13:26".replace( " " , "T" ) );

……和……</p>

LocalDate localDate = LocalDate.parse ( "January 13, 2012" , DateTimeFormatter.ofLocalizedDate ( FormatStyle.LONG ).withLocale ( Locale.US ) );

细节

Jonik的回答基本上是正确的,但遗漏了一些重要问题。

java.time

如果有什么比 Joda 更好的东西,也请告诉我。

是的,有更好的东西,java.time框架。Joda-Time 团队建议迁移到 java.time 作为其继任者。

java.time框架内置于 Java 8 及更高版本中这些类取代了旧的麻烦的日期时间类,例如java.util.Date, .Calendar, & java.text.SimpleDateFormat

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。

许多 java.time 功能在 ThreeTen-Backport 中向后移植到 Java 6 和 7,并在ThreeTenABP进一步适应 Android 。

约会时间

您的第一个输入是日期加上一天中的时间。它缺少任何与 UTC 的偏移量时区信息,因此我们将其解析为LocalDateTime对象。“本地……”是指任何地方,没有特定的地方。所以这不是时间线上的实际时刻,而只是一个关于时刻的粗略概念。

为了解析输入字符串2012-01-10 23:13:26,我们可以将中间的空格替换为 aT以符合ISO 8601标准日期时间值格式的规范样式。

java.time 类在解析和生成日期时间值的文本表示时默认使用 ISO 8601 格式。所以不需要定义解析模式。

String input = "2012-01-10 23:13:26".replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( input );

如果您从该值的上下文中知道预期的时区,则应用它来定义时间线上的实际时刻。

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId );

转储到控制台。

System.out.println ( "input: " + input + " | zdt: " + zdt );

输入:2012-01-10T23:13:26 | zdt: 2012-01-10T23:13:26-05:00[美国/蒙特利尔]

仅限日期

你们中的第二个输入是一个仅日期值,没有时间和时区。为此,我们需要LocalDate类。

我认为该输入的格式符合美国的语言(英语)和文化规范。因此无需明确指定格式模式。我们可以简单地通过指定一个Locale. 我们FormatStyle.LONG根据这种格式的长度指定适当的长度。

String input = "January 13, 2012";
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate ( FormatStyle.LONG ).withLocale ( Locale.US );
LocalDate localDate = LocalDate.parse ( input , formatter );

转储到控制台。

System.out.println ( "input: " + input + " | localDate: " + localDate );

输入:2012 年 1 月 13 日 | 本地日期:2012-01-13

于 2016-07-17T05:32:22.873 回答