使用Java 8解析周字符串以进行比较

时间:2017-01-05 17:11:27

标签: parsing datetime java-8 java-time

我想比较几周的字符串表示,例如周“01/17”在“02/17”之前和“52/16”之后。

以下代码抛出一个异常,我猜是因为我的字符串没有暗示每周的确切日期。但是,我不在乎 - 它可能都是星期一或星期四或其他什么:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ww/YY", Locale.GERMANY);
LocalDate date1 = formatter.parse(str1, LocalDate::from);

我是否需要修改解析器?或者解析其他格式? Unfortunatley几周没有像YearMonth这样的对象......

3 个答案:

答案 0 :(得分:5)

一个解决方案是永远默认为同一天,比如星期一。您可以为此构建自定义格式化程序:

DateTimeFormatter fmt = new DateTimeFormatterBuilder()
          .appendPattern("ww/YY")
          .parseDefaulting(ChronoField.DAY_OF_WEEK, 1)
          .toFormatter(Locale.GERMANY);

您现在可以构建代表给定周的星期一的LocalDate

LocalDate d1 = LocalDate.parse("01/17", fmt);
LocalDate d2 = LocalDate.parse("52/16", fmt);
System.out.println(d1.isAfter(d2));

打印true因为01/17在52/16之后。

答案 1 :(得分:2)

我无法找到使用DateTimeFormatter课程的方法,但我想建议一种不同的方法。

Threeten Extra library包含许多被认为过于具体而无法包含在java.time库中的类。其中一个是你提到的YearWeek课程。

您的问题可以通过从输入字符串手动解析周数和年份然后调用YearWeek创建者方法来解决:

YearWeek yw = YearWeek.of(year, monthOfYear);

答案 2 :(得分:2)

TL;博士

YearWeek.parse( "2017-W01" )

ISO 8601

  

还是解析其他格式?

是的,请使用其他格式。

将日期时间值序列化为文本时,请使用标准ISO 8601格式。该标准包括support for week dates

对于一年的周数,可以是四年的数字,连字符,W和一年中的两位数字。

  

2017-W01

明确您对“周”的定义。 ISO 8601的定义是:

  • 第1周包含一年中的第一个星期四,
  • 周一至周日运行。

所以这些年要么长达52周或53周。请注意,根据此定义,一年中的前几天可能是上周编号周。同样地,一年中的最后几天可能是在下一年的周编号。

如果您想指明该周内的特定日期,请在周一至周日附加一个连字符和一个数字1-7运行。

提示:要在计算机上默认查看ISO 8601周数,您可能需要调整操作系统设置。例如,在macOS上设置系统偏好设置>语言与区域>日历> ISO 8601使Calendar.app等应用程序能够显示具有此标准定义的周数。

  

2017-W01-7

顺便提一下,有几个相似的表示:

  • 序号日期表示年份和从1-366开始的年份号码是年份,连字符和三位数字:2017-123
  • 没有年份的月 - 日是两个连字符,月号,连字符和星期几号:--01-07

请注意,问题中使用的Locale与标准ISO 8601格式无关。

YearWeek

  

Unfortunatley几周没有像YearMonth这样的对象......

啊,但这样的一个类。

如果课程直接代表一周的想法,请参阅correct Answer by Henrik。该答案显示了ThreeTen-Extra图书馆的课程YearWeek

YearWeek类可以直接解析并生成标准格式的字符串。

YearWeek yw = YearWeek.parse( "2017-W01" );

您可以将YearWeek个对象与方法进行比较:compareToequalsisBeforeisAfter

yw.isBefore( thatYw )

ThreeTen-Extra项目提供了其他类,例如YearQuarter,您可能会发现它们很有用。