【问题标题】:Define a date range in Time4j (Persian calendar)在 Time4j(波斯历)中定义日期范围
【发布时间】:2017-09-11 15:38:53
【问题描述】:

我想像这样定义一个日期范围:

  • "1396/8/9"开始
  • 结束于"1396/9/2"

并获取这两个日期之间的天数。

我在网上搜索了一下,发现Time4j中有一个DateInterval函数。

是否可以使用此方法在波斯日历中定义可选日期范围?如果是,我该如何使用这种方法来达到我的目的?

【问题讨论】:

    标签: java calendar persian time4j


    【解决方案1】:

    使用转化

    DateInterval 类是专为 ISO-8601 设计的,它仅适用于公历。因此,您需要自己负责 gregorian 类型 PlainDate 和目标类型 PersianCalendar 之间的转换:

    DateInterval interval =
      DateInterval.between(
        PersianCalendar.of(1396, 8, 9).transform(PlainDate.axis()),
        PersianCalendar.of(1396, 9, 2)).transform(PlainDate.axis());
    

    对于反向转换:

    PersianCalendar start = interval.getStartAsCalendarDate().transform(PersianCalendar.axis());
    

    当然,您也可以每天循环播放您的时间间隔:

    interval
      .streamDaily()
      .map(d -> d.transform(PersianCalendar.axis()))
      .forEach(System.out::println);
    

    旁注:

    DateInterval 默认关闭(在大多数与业务日期相关的应用程序中都需要),但可以通过调用 interval.withOpenEnd() 将其配置为半打开。

    替代方案:

    甚至还有一种方法可以将PersianCalendar 的实例直接存储在一个区间中,即SimpleInterval(注意:在发布v4.31 之前总是半开!)。示例:

    SimpleInterval<PersianCalendar> pInterval =
      SimpleInterval.onTimeLine(PersianCalendar.axis()).between(
        PersianCalendar.of(1396, 8, 9),
        PersianCalendar.of(1396, 9, 2).plus(CalendarDays.ONE)
      );
    

    通过普通的 for 循环进行日常循环:

    for (
      PersianCalendar pcal = pInterval.getStart().getTemporal(); 
      pcal.isBefore(pInterval.getEnd().getTemporal(); 
      pcal = pcal.plus(CalendarDays.ONE)
    ) {
      System.out.println(pcal);
    }
    

    但是,我真的不推荐使用 SimpleInterval,因为 a) 它的功能比 DateInterval 少,并且 b) 主要是为像 java.util.Date 这样的非日历类型设计的(因为这样的间隔总是一半-在大多数业务应用程序中,日历间隔最好关闭)。

    可选范围

    关于您的术语“可选日期范围”,我不清楚其含义。你能澄清一下吗?也许您正在谈论无限或半无限区间边界。这个有可能。只需不要通过between(...) 而是通过since(...)until(...) 构建您的区间。但这会影响您的循环代码(您不能从无穷大或直到无穷大循环。)。

    更新 (2017-10-21)

    从 v4.31 版本开始,SimpleInterval 类已得到增强,因此它可以以更好的方式处理日历类型,即始终关闭而不是半开(但即时间隔仍将是半开, 当然)。为此目的引入了一些新方法,例如on(TimeAxis)。链接后面的 javadoc 显示了一个示例:

     PersianCalendar start = PersianCalendar.of(1392, PersianMonth.ESFAND, 27);
     PersianCalendar end = PersianCalendar.of(1393, PersianMonth.FARVARDIN, 6);
    
     SimpleInterval<PersianCalendar> i1 =
       SimpleInterval.on(PersianCalendar.axis()).between(start, end);
     SimpleInterval<PersianCalendar> i2 =
       SimpleInterval.on(PersianCalendar.axis()).between(
         end.minus(CalendarDays.ONE),
         end.plus(CalendarDays.ONE));
    
     System.out.println(
       interval.findIntersection(
         SimpleInterval.on(PersianCalendar.axis()).between(
           end.minus(CalendarDays.ONE), end.plus(CalendarDays.ONE))).get());
     // [AP-1393-01-05/AP-1393-01-06]
    

    这样的日历间隔可以像往常一样在IntervalCollectionIntervalTree内处理。

    【讨论】:

    • 非常感谢您的有用笔记。 Time4j 中的 DateInterval 是否有任何教程或代码示例来完成我的知识?
    • 关于“可选日期范围”一词,我的意思是与一个月的开始日到月末无关的日期范围。我想将其定义为 2 或 3 个月,并在这两个日期之间指定天数。
    • 完美运行。我可以将这些日期存储在字符串或日期数组中吗?
    • @Sameer 不幸的是,我还没有时间写一个教程页面,特别是关于间隔的(带有示例)。 Time4J-intervals 可以做很多事情。真的应该写一次。关于您的问题如何存储开始或结束,好吧,它是可序列化的,或者您可以将其格式化并解析为字符串。甚至整个区间也是可格式化和可序列化的。
    • @Sameer 关于您的可选日期范围,似乎您正在寻找一种方法来将 2 或 3 个月添加到波斯日历日期以实现间隔的结束。可能是start.with(PersianCalendar.DAY_OF_MONTH.maximized())start.plus(2, PersianCalendar.Unit.MONTHS) 或类似的合适组合为您服务。这不会改变每日循环的逻辑,它适用于每个有限的开始和结束。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 2012-06-02
    • 2018-10-05
    • 1970-01-01
    相关资源
    最近更新 更多