gpt4 book ai didi

java - 将日期时间解析为日历或 simpleDateFormat 的结果不同

转载 作者:行者123 更新时间:2023-11-29 04:20:45 28 4
gpt4 key购买 nike

我现在使用 java 1.6 并遇到奇怪的行为,可能是错误,这是代码:

import org.junit.Test;

import javax.xml.bind.DatatypeConverter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class TestDate {
@Test
public void testConvert() throws Exception {
Calendar parsedCalendar = DatatypeConverter.parseDateTime("0001-01-01T00:00:00");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date sdfDate = simpleDateFormat.parse("0001-01-01T00:00:00");

Calendar parsedCalendar2 = DatatypeConverter.parseDateTime("1980-03-01T00:00:00");
SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date sdfDate2 = simpleDateFormat2.parse("1980-03-01T00:00:00");


System.out.println("parsedCalendar: " + parsedCalendar.getTimeInMillis());
System.out.println("parsedCalendar TZ: " + parsedCalendar.getTimeZone());
System.out.println("parsedCalendar Date: " + parsedCalendar.getTime());
System.out.println("sdfDate: " + sdfDate);
System.out.println("sdfDate millis: " + sdfDate.getTime());

System.out.println("parsedCalendar2: " + parsedCalendar2.getTimeInMillis());
System.out.println("parsedCalendar2 TZ: " + parsedCalendar2.getTimeZone());
System.out.println("parsedCalendar2 Date: " + parsedCalendar2.getTime());
System.out.println("sdfDate2: " + sdfDate2);
System.out.println("sdfDate2 millis: " + sdfDate2.getTime());

}
}

问题来了: debug

输出:

parsedCalendar: -62135622000000
parsedCalendar TZ: sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]
parsedCalendar Date: Mon Jan 03 00:00:00 NOVT 1
sdfDate: Sat Jan 01 00:00:00 NOVT 1
sdfDate millis: -62135794800000

parsedCalendar2: 320691600000
parsedCalendar2 TZ: sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]
parsedCalendar2 Date: Sat Mar 01 00:00:00 NOVT 1980
sdfDate2: Sat Mar 01 00:00:00 NOVT 1980
sdfDate2 millis: 320691600000

调试:

 parsedCalendar.getTimeInMillis() = -62135622000000
sdfDate.getTime() = -62135794800000
parsedCalendar.getTime() = {Date@790} "Mon Jan 03 00:00:00 NOVT 1"
sdfDate = {Date@759} "Sat Jan 01 00:00:00 NOVT 1"
parsedCalendar2.getTimeInMillis() = 320691600000
sdfDate2.getTime() = 320691600000
parsedCalendar2.getTimeZone() = {ZoneInfo@755} "sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]"
parsedCalendar.getTimeZone() = {ZoneInfo@756} "sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]"
simpleDateFormat.getTimeZone() = {ZoneInfo@757} "sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]"
simpleDateFormat2.getTimeZone() = {ZoneInfo@758} "sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]"

正如您在解析 0001 dateTime 时所看到的,以 ms 为单位存在差异!而在解析 1980 时却不是。谁能解释一下为什么?

最佳答案

这是由于儒略历和公历系统之间的差异。

SimpleDateFormat 使用默认的日历系统,我相信它在你的系统和我的系统上都是 GregorianCalendarGregorianCalendar(与其名称不同)根据 gregorianChange 属性在公历系统和儒略历系统之间切换。它假定在​​该切换之后提供的任何日期都是格里高利历,而在它之前提供的任何日期都是儒略历。默认切换时间为 1582。

DatatypeConverter 使用纯公历代替,因为这就是 W3C XML Schema docs require 的内容。 .

这意味着如果您在日历切换之前解析一个值,您会看到很大的差异 - 随着时间的推移,差异会越来越小,差异为 3每 400 年的天数。 (不能被 400 整除的三个世纪年,儒略历中的闰年也是如此,但公历中的闰年也是如此。)

如果您将 SimpleDateFormat 中的日历设置为您首先调用了 setGregorianChange(Long.MIN_VALUE)GregorianCalendar,则两个人会同意。

下面是代码,可以更轻松地探索差异:

import javax.xml.bind.DatatypeConverter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;

public class Test {
public static void main(String[] args) throws ParseException {
convert("0001-01-01T00:00:00");
convert("1000-01-01T00:00:00");
convert("1580-01-01T00:00:00");
convert("1590-01-01T00:00:00");
convert("1980-03-01T00:00:00");
}

private static void convert(String input) throws ParseException {
Calendar datatypeConverterResult = DatatypeConverter.parseDateTime(input);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date sdfResult = simpleDateFormat.parse(input);

System.out.println("Input: " + input);
long datatypeConverterMillis = datatypeConverterResult.getTimeInMillis();
long sdfResultMillis = sdfResult.getTime();
long days = TimeUnit.MILLISECONDS.toDays(datatypeConverterMillis - sdfResultMillis);
System.out.println("DatatypeConverter epoch millis: " + datatypeConverterMillis);
System.out.println("SimpleDateTime epoch millis: " + sdfResultMillis);
System.out.println("Difference in days: " + days);
System.out.println("Parsed calendar time zone: " + datatypeConverterResult.getTimeZone().getID());
System.out.println();
}
}

请注意,在 Java 9 中,您需要明确指定模块。使用 java.se.ee 最简单:

$ javac Test.java --add-modules java.se.ee
$ java --add-modules java.se.ee Test

我的盒子上的输出:

Input: 0001-01-01T00:00:00
DatatypeConverter epoch millis: -62135596800000
SimpleDateTime epoch millis: -62135769600000
Difference in days: 2
Parsed calendar time zone: Europe/London

Input: 1000-01-01T00:00:00
DatatypeConverter epoch millis: -30610224000000
SimpleDateTime epoch millis: -30609792000000
Difference in days: -5
Parsed calendar time zone: Europe/London

Input: 1580-01-01T00:00:00
DatatypeConverter epoch millis: -12307248000000
SimpleDateTime epoch millis: -12306384000000
Difference in days: -10
Parsed calendar time zone: Europe/London

Input: 1590-01-01T00:00:00
DatatypeConverter epoch millis: -11991628800000
SimpleDateTime epoch millis: -11991628800000
Difference in days: 0
Parsed calendar time zone: Europe/London

Input: 1980-03-01T00:00:00
DatatypeConverter epoch millis: 320716800000
SimpleDateTime epoch millis: 320716800000
Difference in days: 0
Parsed calendar time zone: Europe/London

关于java - 将日期时间解析为日历或 simpleDateFormat 的结果不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49317919/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com