当前位置: 首页 > 知识库问答 >
问题:

Java日期时间开始和结束日期,无任何时区信息

田玉韵
2023-03-14

我有两个字符串作为startDate和endDate。这些值如下所示,例如:

startDate="2019-09-29T06:00:00.000Z"
endDate="2019-10-06T05:59:59.999Z"

现在让我们说,这些都是在山区时间作为startDate一天的开始和endDate一天的结束。但由于这些是字符串,我如何让程序理解这些字符串可以转换为山区当地时间,如:

startDate="2019-09-29T00:00:00.000Z"
endDate="2019-10-05T11:59:59.999Z"

时区是html" target="_blank">动态的。我可以从东部时间或任何其他时区获得时间戳字符串。
更新
我意识到我应该输入更多的信息。
所以我输入的Moutain时间就是一个例子。它可以来自东部时间或任何其他时区。此方法知道的唯一事实是,starDate是某个时区中一天的开始,endDate是该时区中一天的结束。我知道'Z'是世界协调时,但找出哪个时区在一天的开始(开始日期)和一天的结束(结束日期)产生了世界协调时,并转换回相应的本地时间,是我面临的挑战。

共有2个答案

程昕
2023-03-14

我的手指离不开这个,很有趣。据我所知,你不知道开始和结束字符串来自哪个时区,它可以是任何时区。我们能做什么,除了轮流尝试它们?

    String startDate = "2019-09-29T06:00:00.000Z";
    String endDate = "2019-10-06T05:59:59.999Z";

    LocalTime dayStart = LocalTime.MIN;
    LocalTime dayEndEarliset = LocalTime.of(23, 59, 59);

    Instant startInstant = Instant.parse(startDate);
    Instant endInstant = Instant.parse(endDate);
    // Just out of curiosity find candidate time zones
    Set<ZoneId> candidateZones = ZoneId.getAvailableZoneIds()
            .stream()
            .map(ZoneId::of)
            .filter(zid -> startInstant.atZone(zid).toLocalTime().equals(dayStart)
                    && ! endInstant.atZone(zid).toLocalTime().isBefore(dayEndEarliset))
            .collect(Collectors.toSet());
    System.out.println("Potential time zones: " + candidateZones);
    // Real work: find candidate date(s)
    Set<LocalDate> candidateDates = ZoneId.getAvailableZoneIds()
            .stream()
            .map(ZoneId::of)
            .filter(zid -> startInstant.atZone(zid).toLocalTime().equals(dayStart)
                    && ! endInstant.atZone(zid).toLocalTime().isBefore(dayEndEarliset))
            .map(zid -> startInstant.atZone(zid).toLocalDate())
            .collect(Collectors.toSet());
    if (candidateDates.isEmpty()) {
        System.out.println("Cannot identify a date from the instants");
    } else if (candidateDates.size() > 1) {
        System.out.println("Ambiguous date, candidates are " + candidateDates);
    } else {
        System.out.println("The date is " + candidateDates.iterator().next());
    }

这张照片是:

Potential time zones: [America/Inuvik, America/Yellowknife, America/Regina, America/Boise, SystemV/MST7MDT, America/El_Salvador, America/Costa_Rica, America/Shiprock, America/Guatemala, America/Denver, America/Belize, America/Swift_Current, America/Managua, Mexico/BajaSur, Canada/Mountain, America/Cambridge_Bay, Navajo, America/Chihuahua, America/Ojinaga, MST7MDT, Pacific/Galapagos, America/Mazatlan, US/Mountain, America/Edmonton, America/Tegucigalpa, Canada/Saskatchewan, Etc/GMT+6, SystemV/CST6]
The date is 2019-09-29

是的,美国/丹佛是预期的候选时区之一。到目前为止,我已经找到了开始日期。您可以以类似的方式找到开始日期和结束日期对。您可能更喜欢老式的循环,而不是流操作。

然而,日期并不总是明确的。让我们试着在太平洋/Pago_Pago时区构造一天的间隔。它在偏移-11:00。

    ZoneId zone = ZoneId.of("Pacific/Pago_Pago");
    LocalDate testDate = LocalDate.of(2019, Month.OCTOBER, 2);
    String startDate = testDate.atStartOfDay(zone).toInstant().toString();
    String endDate = testDate.atTime(LocalTime.of(23, 59, 59, 999_000_000))
            .atZone(zone)
            .toInstant()
            .toString();

现在程序的输出为:

Potential time zones: [Antarctica/McMurdo, Pacific/Niue, Pacific/Samoa, Pacific/Tongatapu, Pacific/Enderbury, Etc/GMT+11, NZ, Antarctica/South_Pole, Etc/GMT-13, Pacific/Pago_Pago, Pacific/Midway, Pacific/Fakaofo, US/Samoa, Pacific/Auckland]
Ambiguous date, candidates are [2019-10-03, 2019-10-02]

这是因为也有偏移13:00的时区。我们可以判断偏移量一定是-11:00或13:00,但我们无法判断两者中的哪一个。所以两个日期出来了。

使用半开放的时间间隔

我不确定结尾是否总是在有关时区的23:59:59.999,或者有时可能是23:59:59.999999或其他什么。此外,无论我们添加多少小数,理论上仍然存在在结束时间之后但仍在同一日期内的时刻。在代码中,我保守地接受23:59:59及以后的任何时间作为结束时间。完全避免疑问的要点是:使用半开区间。将间隔的开始表示为00:00:00,并将结束表示为最后一个日期之后的日期中的00:00:00。并将开始日期视为包容性,将结束视为排他性。

华昕
2023-03-14

末尾的Z是时区信息,意味着从UTC,也称为零,也称为Zulu的偏移量00:00,因此首先将字符串解析为存储日期、时间和Z时区的类型。

使用Java 8时间API,这将是即时偏移日期时间,或分区日期时间
如果您的输入总是以Z结束,而不是其他偏移,请使用即时

然后,您将转换到所需的时区,对于我们来说,山区时间称为美国/丹佛

实例

String startDate = "2019-09-29T06:00:00.000Z";
String endDate = "2019-10-06T05:59:59.999Z";
ZoneId zone = ZoneId.of("America/Denver");

System.out.println(Instant.parse(startDate).atZone(zone));
System.out.println(OffsetDateTime.parse(startDate).atZoneSameInstant(zone));
System.out.println(ZonedDateTime.parse(startDate).withZoneSameInstant(zone));

System.out.println(Instant.parse(endDate).atZone(zone));
System.out.println(OffsetDateTime.parse(endDate).atZoneSameInstant(zone));
System.out.println(ZonedDateTime.parse(endDate).withZoneSameInstant(zone));

输出

2019-09-29T00:00-06:00[America/Denver]
2019-09-29T00:00-06:00[America/Denver]
2019-09-29T00:00-06:00[America/Denver]
2019-10-05T23:59:59.999-06:00[America/Denver]
2019-10-05T23:59:59.999-06:00[America/Denver]
2019-10-05T23:59:59.999-06:00[America/Denver]

如果您不想在转换后保留时区,可以通过调用toLocalDateTime()将其删除,例如。

System.out.println(Instant.parse(endDate).atZone(zone).toLocalDateTime());

输出

2019-10-05T23:59:59.999

注意,它的末尾没有一个Z

 类似资料:
  • 问题内容: 我想检查日期是否在开始日期和结束日期之间。 我添加了一个where子句 但问题在于它不包含“ 2010-04-15”。 它应该包括结束日期,我该怎么办? 请帮我 问候, 潘卡 问题答案: 明确指定时间部分:

  • 问题内容: 如果可能的话,在以下情况下,我希望使用joda或非joda解决方案 假设我的一周从2012年5月2日开始,给定的当前日期为02/22/2011。我需要计算给定当前日期的星期开始和结束日期。因此,我的解决方案的星期应该从02/19开始,而星期在02/25结束。为简单起见,我将我的工作日设置为02/05/2011,但是可能是任何一天,我的工作日始终为7天。 我现有的代码如下,但似乎无法按预

  • 我想在日期时间选择器中选择大于开始日期的结束日期时间。 当前,我正在开始日期时间和结束日期时间。 假设,我选择了时间为12:00 pm的当前日期,现在end date应该是时间为1:00 pm的当前日期。 我想要下面这样的东西 示例 开始日期和时间:---2019-11-06 12:00结束日期和时间:---2019-11-06 1:00 这是我的代码 null null

  • 我试图找出明星日期和结束日期的员工时钟。以下是我所掌握的数据示例。 需要输出: 我必须根据eventtime和activitycode找到此人的开始日期和结束日期。开始日期将是事件时间列,我必须从行中下一个事件时间的同一列计算结束日期。 我曾尝试在T-SQL中使用lead函数,但它并没有给出我想要的结果。 如果有人知道如何处理这个问题,我会非常感激。

  • 问题内容: 我有一个事件表,其中记录了一个开始和结束时间,作为MySQL DATETIME对象(格式。我想查找在特定日期范围内发生的所有事件。但是,事件可能跨越多天(并且超出了我的范围)日期范围,但是如果它们与我的日期范围重叠1秒或更长时间,我想返回它们。 有什么建议吗? 问题答案: 这将找到范围内完全包含的每个事件: 这将查找事件的任何部分与范围的任何部分重叠的任何事件:

  • 问题内容: 我有一张关于不同资产的开/关事件的表格。我需要在不使用游标的情况下获取开始和停止事件时间的列表。 来源: 所需结果: 问题答案: 这是解决方案,带有概念验证供所有人验证。 我注意到的事件被标记为新事件。我解决了这个问题,但是这也导致我编写了一个解决方案,该解决方案允许发生一个已经开始但尚未结束的事件,因此我加入了一个开放式事件。 另外,我的解决方案在重叠的时期内有效。 讲解 我们将数据