【问题标题】:Parse week strings for comparison using Java 8使用 Java 8 解析星期字符串以进行比较
【发布时间】:2017-01-05 17:11:26
【问题描述】:

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

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

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

我需要修改解析器吗?还是解析成其他格式?不幸的是,几周内没有像 YearMonth 这样的对象......

【问题讨论】:

  • 您在这里对“一周”的定义到底是什么?

标签: parsing datetime java-8 java-time


【解决方案1】:

一种解决方案是始终默认为同一天,例如星期一。您可以为此构建自定义格式化程序:

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

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

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 之后。

【讨论】:

  • 太好了,parseDefaulting() 是缺失的部分 :)
【解决方案2】:

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

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

您的问题可以通过从输入字符串中手动解析周数和年份来解决,然后像这样调用YearWeek creator-method:

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

【讨论】:

  • 谢谢,很高兴知道这个库。我发现非常奇怪的是,通过模式字符串构建的格式化程序无法提供使用 from() 创建 YearWeek 所需的详细信息。但是,通过 DateTimeFormatterBuilder 构造的一个可以工作。不过,这很不幸,因为我想从 config 提供模式。
  • @Tom 或者——还有更多附加功能——还有我的库 Time4J,它提供了 CalendarWeek 类,包括良好的 i18n 支持和周算术(使用 plusWeeks() 等方法)。两者都在 Threeten-Extra 中丢失。但仅用于比较日历周,似乎没有必要添加额外的依赖项。
【解决方案3】:

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 上设置 System Preferences > Language & Region > Calendar > ISO 8601 以使 Calendar.app 等应用程序使用此标准定义显示周数。

2017-W01-7

顺便说一下,有几个类似的表示:

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

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

YearWeek

不幸的是,几周内没有像 YearMonth 这样的对象......

啊,但是有这样的类。

对于直接代表一周年概念的类,请参阅correct Answer by Henrik。该答案显示了ThreeTen-Extra 库的类YearWeek

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

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

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

yw.isBefore( thatYw )

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

【讨论】:

    猜你喜欢
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 2017-02-20
    • 2010-10-06
    • 1970-01-01
    相关资源
    最近更新 更多