【问题标题】:Way to get end points of a time interval based on a date?如何根据日期获取时间间隔的终点?
【发布时间】:2022-01-19 18:39:29
【问题描述】:

我想我可以自己做这件事,但如果我不需要的话,我不想重新发明轮子(尤其是关于日期算术)。

我正在制作一个带有下拉菜单的摇摆应用程序,用户可以在其中选择时间间隔,选项为All, Today, This Week, This Month, This Quarter, This Year, Last Week, Last Month, Last Quarter, Last Year。当用户选择其中之一时,我想计算间隔。

例如,今天是 2022 年 1 月 19 日。如果有人选择了This Week,我的startDate 将是2022-01-16 00:00:00,而我的endDate 将是2022-01-22 11:59:59(或者2022-01-23 00:00:00 可能更有意义?)

对于All 选择,我已经实现了一种方法,其中我的startDate 是1970 年1 月1 日,而我的endDate 是从当前时间到未来几年的时间。我也可以自己做Today,只需获取今天的日期并调整从午夜到午夜的时间。

但是对于所有这些其他选项,我不知道是否已经有一个库或类似的库计算了我可以利用的它们。很久没接触java了,对生态系统不太了解。

同样重要的是 endDate 和 startDates 要么是 java.util.Date 类型,要么是它的子类,因为我需要将它与依赖它的代码集成。

任何指针将不胜感激。

【问题讨论】:

  • 我强烈建议您使用 java.time 类型进行日期数学运算,并仅在必要时转换为 java.util.Date。例如,TemporalAdjusters 是一个很好的起点。
  • 啊,时间调节器看起来正是我所需要的——谢谢!
  • 请注意,星期日并不是世界上每个国家/地区每周的第一天。我认为您的 Swing 应用程序不需要国际化,对吗?
  • 正确,它是一个非常小的应用程序,本地用户群很小。
  • 一旦您了解了一些基本概念,计算时区并不是真正的额外工作。并且保持您的代码时区精通可以在以后避免伤害世界。

标签: java date


【解决方案1】:

我会使用java.time.LocalDate,您可以从java.util.Date 轻松获取并在需要时来回转换。

以下是使用LocalDate 获取当前星期开始的方法(使用美国语言环境,如果星期开始不同,您可以使用其他内容)

LocalDate now = LocalDate.now();
TemporalField fieldUS = WeekFields.of(Locale.US).dayOfWeek();
System.out.println(now.with(fieldUS, 1)); 

您可以通过一些搜索从其他 StackOverflow 帖子中找到如何满足您的其余要求。

以下是如何将Date 转换为LocalDate

Date date = new Date();
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

并从LocalDate 转换为Date

LocalDate localDate = LocalDate.now();
Date date = Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());

【讨论】:

    【解决方案2】:

    时区

    你说:

    例如,今天是 2022 年 1 月 19 日。如果有人选择了本周,我的 startDate 将是 2022-01-16 00:00:00

    请注意,确定时刻需要时区。 16 日 00:00 的时间在日本东京比美国俄亥俄州托莱多早了几个小时。

    此外,在某些时区的某些日期,一天并非从 00:00 开始。与其假设,不如让 java.time 确定一天中的第一个时刻。

    ZoneId zTokyo = ZoneId.of( "Asia/Tokyo" ) ;
    ZonedDateTime todayStartTokyo = ZonedDateTime.now( zTokyo ).toLocalDate().atStartOfDay( zTokyo ) ;
    

    一个月,使用java.time.YearMonth

    ZoneId zAuckland = ZoneId.of( "Pacific/Auckland" ) ;
    LocalDate ld = LocalDate.of( 2022 , 1 , 19 ) ;
    YearMonth ym = YearMonth.from( ld ) ;
    

    确定日期范围。

    LocalDate dateStart = yw.atDay( 1 ) ;
    LocalDate dateEnd = yw.plusMonths( 1 ) ;
    

    确定时刻。

    ZonedDateTime zdtStart = dateStart.atStartOfDay( zAuckland ) ;
    ZonedDateTime zdtEnd = dateEnd.atStartOfDay( zAuckland ) ;
    

    季度

    如果您对宿舍的定义与 ISO 8601 的定义一致,我建议将 ThreeTen-Extra 库添加到您的项目中,用于其 org.threeten.extra.Quarter 枚举和 org.threeten.extra.YearQuarter 类。

    同样,该类中使用的星期定义符合 ISO 8601。如果您的定义不同,则该类将不适合您。 ISO 8601 周从星期一开始,一直持续到星期日,一年中的第 1 周是日历年的第一个星期四,结果为 52 或 53 - 每年每周工作 7 天。

    LocalDate ld = LocalDate.of( 2022 , 1 , 19 ) ;
    YearQuarter yq = YearQuarter.from( localDate ) ;
    LocalDate yqStart = yq.atDay( 1 ) ;
    LocalDate yqEnd = yq.plusQuarters( 1 ).atDay( 1 ) ;
    

    瞬间范围相同:

    ZoneId zTunis = ZoneId.of( "Africa/Tunis" ) ;
    ZonedDateTime zdtStart = yqStart.atStartOfDay( zTunis ) ;
    ZonedDateTime zdtEnd = yqEnd.atStartOfDay( zTunis ) ;
    

    与宿舍一样,对于几周的工作,我建议为其org.threeten.extra.YearWeek 类添加ThreeTen-Extra 库。内置 java.time 确实有一些周功能,但它们是有限的。

    ZoneId zEdmonton = ZoneId.of( "America/Edmonton" ) ;
    LocalDate todayEdmonton = LocalDate.now( zEdmonton ) ;
    YearWeek yw = YearWeek.from( todayEdmonton ) ;
    

    或者,只是:

    YearWeek yw = YearWeek.now( zEdmonton ) ;
    

    确定日期范围:

    LocalDate weekStart = yw.atDay( DayOfWeek.MONDAY ) ;
    LocalDate weekEnd = yw.plusWeeks( 1 ).atDay( DayOfWeek.MONDAY ) ;
    

    要确定一系列时刻,请使用上面看到的相同代码,调用atStartOfDay

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-21
      • 2012-05-06
      • 1970-01-01
      • 2019-01-13
      • 2020-04-23
      • 1970-01-01
      相关资源
      最近更新 更多