【问题标题】:Jodatime start of day and end of dayJodatime 一天的开始和一天的结束
【发布时间】:2012-02-27 12:36:47
【问题描述】:

我想在一周的开始和当前一周的结束之间创建一个间隔。

我有以下代码,借自this answer

private LocalDateTime calcNextSunday(LocalDateTime d) {
    if (d.getDayOfWeek() > DateTimeConstants.SUNDAY) {
        d = d.plusWeeks(1);
    }
    return d.withDayOfWeek(DateTimeConstants.SUNDAY);
}

private LocalDateTime calcPreviousMonday(LocalDateTime d) {
    if (d.getDayOfWeek() < DateTimeConstants.MONDAY) {
        d = d.minusWeeks(1);
    }
    return d.withDayOfWeek(DateTimeConstants.MONDAY);
}

但现在我希望星期一 LocalDateTime 位于 00:00:00,而星期日 LocalDateTime 位于 23:59:59。我该怎么做?

【问题讨论】:

  • 从时间间隔的末尾减去一个“小单位”总是一个非常的坏主意。时间间隔包括其开始和不包括其结束。检查(日期)时间是否包含在您执行的时间间隔中:开始

标签: java android jodatime


【解决方案1】:

您可以使用withTime 方法:

 d.withTime(0, 0, 0, 0);
 d.withTime(23, 59, 59, 999);

与彼得的答案相同,但更短。

【讨论】:

  • 一天的开始也可以用 d.withTimeAtStartOfDay()
  • withTimeAtStartOfDay() 不可用于LocalDateTime,但可用于DateTime
  • 请记住,使用这种方法,您每天会损失一毫秒。我建议在那天结束时使用d.plusDays(1).withTime(0, 0, 0, 0)
  • 最好使用plusDays(1).withTime(0,0,0,0) 方法,正如@Feuermurmel 指出的那样,因为它适用于闰秒,至于 2015-06-30T23:59:60
  • 注意夏令时。最好使用d.millisOfDay().withMaximumValue();
【解决方案2】:

还有一个简单的方法是

d.millisOfDay().withMaximumValue();

【讨论】:

  • 这应该是公认的答案,与其他答案相比,在性能方面是最好的(创建的对象较少,因为 DateTime 是不可变的)。 withMaximunValue Documentation 的方法甚至说是完成问题的最佳方法
  • getMaximumValueOverall有什么区别?
【解决方案3】:

怎么样:

private LocalDateTime calcNextSunday(LocalDateTime d) {
    return d.withHourOfDay(23).withMinuteOfHour(59).withSecondOfMinute(59).withDayOfWeek(DateTimeConstants.SUNDAY);
}

private LocalDateTime calcPreviousMonday(final LocalDateTime d) {
    return d.withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withDayOfWeek(DateTimeConstants.MONDAY);
}

【讨论】:

  • setXxx 按照惯例在 Java 中没有返回类型,因此它不允许链接。这让我们想起了构建器模式(最初不适用于现有对象)。
  • 确实如此。这使您可以将调用串在一起,而不是将它们全部放在不同的行上,并让您获得不可变对象的所有好处。
  • 我认为“模式”被称为“Fluent interface”martinfowler.com/bliki/FluentInterface.html - 在我看来,在可读性和清晰度方面有很多好处。
  • 我在 2006 年写了“with”动词 - blog.joda.org/2006/05/immutable-pojos-improving-on_6406.html 并在 2011 年更新了 - blog.joda.org/2011/08/common-java-method-names.html。不可变 setter 与普通 setter 的使用方式有很大不同(必须使用返回值)。
  • @TheRueger 响应是最佳答案。这个是正确的,但在当前答案中性能最差,因为它在每个 withXXX 方法中创建了许多对象。 d.millisOfDay().withMaximumValue();是实现最佳方式的方法。
【解决方案4】:

使用 Kotlin,您可以编写扩展函数:

fun DateTime.withTimeAtEndOfDay() : DateTime = this.withTime(23,59,59,999)

这将允许您编写:

d.withDayOfWeek(DateTimeConstants.SUNDAY).withTimeAtEndOfDay()

【讨论】:

    【解决方案5】:

    对于那些来这里寻找“js-joda”答案的人,您有两个选择,具体取决于您要完成的任务

    选项 1:您希望在同一时区开始一天

    由于您选择根据与时区相关的瞬间计算时间,因此您应该使用 ZonedDateTime:

    import { ZonedDateTime, LocalDate, ZoneId, DateTimeFormatter} from "js-joda";
    import 'js-joda-timezone';
    
    const nowInNewYorkCity = ZonedDateTime.now(ZoneId.of("America/New_York"))
    const startOfTodayInNYC = nowInNewYorkCity.truncatedTo(ChronoUnit.DAYS);
    console.log(startOfTodayInNYC.toString()) // Prints "2019-04-15T00:00-04:00[America/New_York]"
    // And if you want to print it in ISO format
    console.log(startOfTodayInNYC.format(DateTimeFormatter.ISO_INSTANT)) // "2019-04-14T04:00:00Z"
    

    选项 2:您知道自己想抽出时间的确切日期

    然后您可以使用 LocalDate 之外的以下方法来得出您想要的相对时间(即 ZonedDateTime):

        atStartOfDay(): LocalDateTime
        atStartOfDay(zone: ZoneId): ZonedDateTime
        atStartOfDayWithZone(zone: ZoneId): ZonedDateTime
    

    选项 3:我只想要瞬间发生的那一天

    注意这段代码,你会得到与你所在位置相关的日期。因此,对于纽约市的人来说,它是“2019-04-14”,而对于伦敦的人来说,它是“2019-04-15”(太棒了!),因为时间的瞬间是在它所在的时间段内实际上明天在伦敦(“2019-04-15T00:00:05Z”)。假设你从纽约给伦敦的某人打电话,伦敦人会说,“天啊,你为什么这么早给我打电话……现在已经过了午夜 5 秒。”

    import { ZonedDateTime, LocalDate, ZoneId} from "js-joda";
    import 'js-joda-timezone';
    
    const aTimeWhenLondonIsAlreadyInTomorrow = "2019-04-15T00:00:05.000Z";
    const inBetweenTimeInLondon = ZonedDateTime.parse(aTimeWhenLondonIsAlreadyInTomorrow);
    const inBetweenTimeInNYC = inBetweenTimeInLondon.withZoneSameInstant(ZoneId.of("America/New_York"))
    const dayInLondon = inBetweenTimeInLondon.toLocalDate();
    const dayInNYC = inBetweenTimeInNYC.toLocalDate();
    console.log(inBetweenTimeInLondon.toString()); // "2019-04-15T00:00:05Z"
    console.log(dayInLondon.toString()); // "2019-04-15"
    console.log(inBetweenTimeInNYC.toString()) // "2019-04-14T20:00:05-04:00[America/New_York]"
    console.log(dayInNYC.toString()); // "2019-04-14"
    

    参考:https://js-joda.github.io/js-joda/class/src/LocalDate.js~LocalDate.html#instance-method-atStartOfDayWithZone

    【讨论】:

      【解决方案6】:
      begin = d
          // Go to previous or same Sunday
          .with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY))
          // Beginning of day
          .truncatedTo(ChronoUnit.DAYS)
      
      end = d
          // Go to next Sunday
          .with(TemporalAdjusters.next(DayOfWeek.SUNDAY))
          // Beginning of day
          .truncatedTo(ChronoUnit.DAYS)
      

      我还认为在实际的排他结束之前用少量时间来表示周末间隔是一个坏主意。最好将开始视为包含,而将结束视为排他(在进行比较等时)。

      【讨论】:

        猜你喜欢
        • 2012-10-30
        • 1970-01-01
        • 1970-01-01
        • 2021-10-24
        • 2014-11-25
        • 1970-01-01
        • 1970-01-01
        • 2018-09-29
        • 2012-01-28
        相关资源
        最近更新 更多