如何检查本地化的日期时间在Java或JS中是否有效

时间:2016-12-09 01:22:23

标签: javascript java timezone dst

我相信应该有一个lib来检查这个。我想知道是否有一个java或javascript。

例如,如果时区位于美国/洛杉矶,2016/03/13/02:20am由于夏令时而不是有效的日期时间。

3 个答案:

答案 0 :(得分:2)

的Java

使用DateTimeFormatter对象解析字符串以获得ZonedDateTime。如果无法解析字符串,则抛出DateTimeParseException。捕获该异常。

您可以通过调用DateTimeFormatter.ofLocalized…方法之一来获取本地化格式化程序。

Stack Overflow已经多次讨论过这个问题。所以搜索代码示例和更多讨论。

您的示例数据不正确。 NSString *userName = [arrayswipe.yourObject valueForKey:@"username"]; 的DST切换确实是2016-03-13,但这是从早上2点到凌晨3点的“春天前进”调整。所以上午01:20的时间是没有问题的。您想要一个示例时刻为America/Los_Angeles,时间为凌晨2点。但即使这是由java.time处理的。在这种情况下应用时区的行为是提前一小时。阅读文档并确保您了解其行为。

2016-03-13T02:20:00
  

输入:2016-03-13T02:20:00 | zdt:2016-03-13T03:20-07:00 [America / Los_Angeles]

请参阅live code in IdeOne.com

要更改此行为,请使用ResolverStyleDateTimeFormatter。已经在Stack Overflow上讨论过;搜索代码示例和更多信息。

ISO 8601

BIG TIP#1: 使用本地化字符串交换日期时间数据。使用ISO 8601格式。该标准是为此目的而发明的。在解析/生成字符串时,java.time类默认使用这些格式。

BIG TIP#2:尽可能坚持UTC值,而不是划分区域。

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 1 :(得分:1)

Answer for Java:

The local timestamp "2016/03/13/01:20am" is indeed valid in Los Angeles, but one hour later we have a gap between standard time and summer time:

String input = "2016/03/13/02:20am";
ZoneId pst = ZoneId.of("America/Los_Angeles");

DateTimeFormatter fmtr =
  new DateTimeFormatterBuilder()
    .appendPattern("uuuu/MM/dd/hh:mm")
    .parseCaseInsensitive()
    .appendText(ChronoField.AMPM_OF_DAY)
    .toFormatter()
    .withLocale(Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(input, fmtr);

System.out.println(ldt); // 2016-03-13T02:20
System.out.println(ldt.atZone(pst)); // 2016-03-13T03:20-07:00[America/Los_Angeles]
System.out.println(
    "Valid local timestamp: " + !pst.getRules().getValidOffsets(ldt).isEmpty()); // false

So we see that the new java.time-package built into Java-8 offers an API how to determine the validitiy of local timestamps in any timezone. It should also be noted that the solution presented does NOT need any way of exception catching.

When converting invalid local timestamps to an instant/moment then only one fixed transition strategy is used, namely to push forward the local timestamp by the size of the gap between winter and summer time, see example above for conversion to an object of type ZonedDateTime.


Side note: If people are not on Java-8 or if they look for a slightly more elegant alternative then using my library Time4J might be an alternative:

String input = "2016/03/13/02:20am";

PlainTimestamp tsp =
    ChronoFormatter.ofTimestampPattern(
        "uuuu/MM/dd/hh:mma",
        PatternType.CLDR,
        Locale.ENGLISH
    ).parse(input);

System.out.println(tsp); // 2016-03-13T02:20
System.out.println("Valid local timestamp: " + tsp.isValid(AMERICA.LOS_ANGELES)); // false

When converting local timestamps to an instant/moment then the transition strategy is configurable (in contrast to standard Java):

    // simulation of JDK-behaviour: 2016-03-13T10:20:00Z (= 2016-03-13T03:20:00-07:00)
    System.out.println(tsp.in(Timezone.of(AMERICA.LOS_ANGELES)));

    // jump to next valid time: 2016-03-13T10:00:00Z (= 2016-03-13T03:00:00-07:00)
    System.out.println(
        tsp.in(
            Timezone.of(AMERICA.LOS_ANGELES).with(
                GapResolver.NEXT_VALID_TIME.and(OverlapResolver.EARLIER_OFFSET)
            )
        )
    );

    // throws an exception for invalid timestamp (similar to Joda-Time-library)
    // => Invalid local timestamp due to timezone transition: 
    // => local-date=2016-03-13, local-time=T02:20 [LOS_ANGELES]
    tsp.in(
        Timezone.of(AMERICA.LOS_ANGELES).with(
            GapResolver.ABORT.and(OverlapResolver.EARLIER_OFFSET)
        )
    );

Foot note: As mentioned above, the popular library Joda-Time always throws an exception if the conversion of an invalid LocalDateTime to a DateTime is tried. This effect can be used for determining if the local date-time is valid or not (by exception catching).

Answer for JavaScript:

I am not an expert for JavaScript, but I have found via Google this function in the library MomentJS. Citation:

Is DST Shifted From 2.3.0, Deprecated 2.14.0

moment('2013-03-10 2:30', 'YYYY-MM-DD HH:mm').isDSTShifted()

Note: As of version 2.14.0 this function is deprecated. It doesn't give the right answer after modifying the moment object. For more information refert to moment/3160

Another important piece of validation is to know if the date has been moved by a DST. For example, in most of the United States: moment('2013-03-10 2:30', 'YYYY-MM-DD HH:mm').format(); //=> '2013-03-10T01:30:00-05:00'

This is because daylight saving time shifts the time from 2:00 to 3:00, so 2:30 isn't a real time. The resulting time is browser-dependent, either adjusting the time forward or backwards. Use moment#isDSTShifted to test for this condition.

Note: before 2.3.0, Moment objects in this condition always returned false for moment#isValid; they now return true.

JavaScript-experts may find better solutions and are kindly asked to present here.

答案 2 :(得分:1)

只是为JavaScript添加答案 - Meno正确地选择了Moment.js。我会补充一些细节。

不幸的是,我们不能简单地问一下日期/时间是否落入差距,因为引擎盖下的JS Date对象做了一些时髦的事情,而不是在规范中的转移,并且在不同的环境中不一致。 Moment曾经有一个函数isDSTShifted,但因此被弃用了。最终,一个人真的需要原始输入作为比较的基础来判断时间是否已经转移,并且由于人们可能已经操纵了一下(加,减,设置等),我们没有办法提供更好的实施。

但是 - 由于你确实有特定的输入,你可以通过将输出与相同格式的输入进行比较来自己做,并看看它是否仍然相同。

var s = "2016/03/13/02:20am";
var f = "YYYY/MM/DD/hh:mma";
var shifted = moment(s, f).format(f) !== s;

如果您想使用指定的时区,则还需要使用moment-timezone插件。

var s = "2016/03/13/02:20am";
var f = "YYYY/MM/DD/hh:mma"
var z = "America/Los_Angeles";
var shifted = moment.tz(s, f, z).format(f) !== s;