NNN在日期格式<YYMMDDhhmmssNNN><C|D|G|H>中是什么意思?

What does NNN mean in date format <YYMMDDhhmmssNNN><C|D|G|H>?

嗨,我有日期格式,我想转换为正确的 GMT 日期:

该日期的示例值: 210204215026000C

我得到了 NNN 部分的解释:

NNN     If flag is C or D then NNN is the number of hours relativeto GMT,
        if flag is G or H, NNN is the number of quarter hours relative to GMT
C|D|G|H C and G = Ahead of GMT, D and H = Behind GMT

但我不知道相对于 GMT 的小时数如何以 3 位数显示?它应该是 2 位数字,因为我知道与 GMT 相关的小时偏移量是从 0 到 23,以及相对于 GMT 的四分之一小时是什么意思?

我想使用 Scala 或 Java。

我不知道他们为什么要留出3位作为偏移量。我同意你的看法,所有情况下 2 位数就足够了。也许他们只是想非常确定他们永远不会 运行 of out space,也许他们甚至有点过头了。 3 位数不是问题,只要实际值在 java.time.ZoneOffset 可以处理的范围内,即 +/-18 小时。在您的示例中,NNN000,因此距格林威治标准时间 0 小时,这当然没问题,而且处理起来很简单。

一刻钟就是一刻钟。正如 Salman A 在评论中提到的那样,比格林威治早 22 刻钟意味着偏移 +05:30,目前在斯里兰卡和印度使用。如果字符串的制作者想要使用此选项,他们可以提供最多 72 个数字(仍然在 2 位数字以内)。 18 * 4 = 72,所以 18 小时等于 72 个刻钟。想象一下 2 位数太少的情况,想想 25 小时的偏移量。我认为这不现实,另一方面没有人能保证它永远不会发生。

Java解决方案:如何解析并转换为GMT时间

我正在使用这些常量:

private static final Pattern DATE_PATTERN
        = Pattern.compile("(\d{12})(\d{3})(\w)");
private static final DateTimeFormatter FORMATTER
        = DateTimeFormatter.ofPattern("uuMMddHHmmss");
private static final int SECONDS_IN_A_QUARTER_HOUR
        = Math.toIntExact(Duration.ofHours(1).dividedBy(4).getSeconds());

像这样解析和转换:

    String sampleValue = "210204215026000C";
    Matcher matcher = DATE_PATTERN.matcher(sampleValue);
    if (matcher.matches()) {
        LocalDateTime ldt = LocalDateTime.parse(matcher.group(1), FORMATTER);
        int offsetAmount = Integer.parseInt(matcher.group(2));
        char flag = matcher.group(3).charAt(0);

        // offset amount denotes either hours or quarter hours
        boolean quarterHours = flag == 'G' || flag == 'H';
        boolean negative = flag == 'D' || flag == 'H';
        if (negative) {
            offsetAmount = -offsetAmount;
        }
        ZoneOffset offset = quarterHours
                ? ZoneOffset.ofTotalSeconds(offsetAmount * SECONDS_IN_A_QUARTER_HOUR)
                : ZoneOffset.ofHours(offsetAmount);

        OffsetDateTime dateTime = ldt.atOffset(offset);
        OffsetDateTime gmtDateTime = dateTime.withOffsetSameInstant(ZoneOffset.UTC);

        System.out.println("GMT time: " + gmtDateTime);
    }
    else {
        System.out.println("Invalid value: " + sampleValue);
    }

输出为:

GMT time: 2021-02-04T21:50:26Z

我认为我的代码涵盖了所有有效案例。您可能想要验证标志确实是 C、D、G 或 H,并且还处理解析和创建 ZoneOffset (NumberFormatException 不应该发生)。