Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在java中处理负ISO 8601日期字符串?_Java_Date_Simpledateformat_Iso8601_Datetime Parsing - Fatal编程技术网

如何在java中处理负ISO 8601日期字符串?

如何在java中处理负ISO 8601日期字符串?,java,date,simpledateformat,iso8601,datetime-parsing,Java,Date,Simpledateformat,Iso8601,Datetime Parsing,我正在尝试将ISO8601日期字符串转换为纪元时间。我如何处理负面日期?下面的代码正确吗?我是否应该使用其他东西而不是简单的日期格式库?负面日期是指BC String formatString = "yyyy-MM-dd'T'hh:mm:ssX"; SimpleDateFormat formatter = new SimpleDateFormat(formatString); Date date = formatter.parse("-2017-01-04T12:30:00+05:00"); S

我正在尝试将ISO8601日期字符串转换为纪元时间。我如何处理负面日期?下面的代码正确吗?我是否应该使用其他东西而不是简单的日期格式库?负面日期是指BC

String formatString = "yyyy-MM-dd'T'hh:mm:ssX";
SimpleDateFormat formatter = new SimpleDateFormat(formatString);
Date date = formatter.parse("-2017-01-04T12:30:00+05:00");
System.out.println(date.getTime()/1000);

Answer: -125818806600L

TL;DR:不,您的代码不正确。是的,我建议使用现代Java日期和时间API而不是
SimpleDataFormat

你的第一个问题是在共同纪元(BCE,“在基督之前”)之前的几年里定义正确性

正如我所读到的,ISO 8601没有明确定义如何解释该范围内的日期。这一年本身没有什么大问题:“0000年等于公元前1年”,因此-1是公元前2年,-2017是公元前2018年。您可以使用前公历(proleptic Gregorian calendar),将公历向后延伸到1582年正式引入之前的日期,但请注意,这与传统上使用的儒略历不一致,因此,当日期时间字符串表示1月4日时,这与历史书中的1月4日不同。此外,ISO 8601并未要求使用负数年和适当的公历,只能通过双方之间的协议。保留:我不知道历史书中是否有关于公元前2018年1月4日的定义;我们回到了朱利安历法(由朱利叶斯·凯撒于公元前46年提出)问世之前

没有说明在引入公历之前它是如何处理日期的。它似乎依赖于与日期/时间格式化程序关联的
日历
对象。这样的
日历
对象在大多数计算机和JVM上都是
gregorianalendar
,但并不总是这样。因此,我认为代码的输出不能保证在所有计算机上都是相同的。而且
Gregorianalendar
可以而且通常确实处理儒略历法中教皇格雷戈之前的日期,因此我希望您得到的结果与历史书一致,但与ISO 8601不一致,当确定哪一天是公元前2018年1月4日时。因此,基于这些理由,我怀疑你的结果是不正确的

作为测试,我将代码的输出与类似使用Java日期和时间API的输出进行了比较。运行您的代码我也得到了
-125818806600
。所以我试着:

    System.out.println(OffsetDateTime.parse("-2017-01-04T12:30:00+05:00")
            .toInstant()
            .getEpochSecond());
这些类应该符合ISO8601标准,所以我更喜欢这段代码而不是你的代码(它也稍微简单一点)。我得到

这是不一样的,所以这是代码没有给出正确结果的另一个迹象。差值为1512000秒,与17天12小时相同。让我先承认我不明白。我很容易认为,儒略历和公历之间的差异可以解释17天或18天之间的差异。但是12个小时让我困惑

编辑:这12个小时来自您在格式模式字符串中使用小写字母
hh
。因为您没有AM/PM标记,所以应该使用大写的
HH
。更正此错误后,代码的输出为

-125818763400
现在,你的代码和我的代码之间的差异是1468800秒,也就是17天


hh
表示范围为1-12的上午或下午的小时数。大写
HH
表示一天中的小时,0-23。这是
SimpleDataFormat
中的一个非常常见的错误(不是现代类,它们会捕获它,所以您可以更正它)。它经常被忽视,因为在大多数时间里,结果都是一样的
SimpleDataFormat
很乐意使用AM作为默认值,解析例如14:30,并将其理解为下午2:30。但是,由于字符串中的时间恰好是12小时,所以有一个区别:上午12:30表示一天中的0:30,而在ISO中,12:30表示下午12:30。因此出现了12小时的错误。

什么是负日期?您有什么日历,其中
-2017-01-04
是一个有效日期?如果您想在大纪元前一年,然后在大纪元后一年定一年,然后否定。请你澄清一下你想要达到的目标——耶稣之前的日期?否定的日期是指BC@ScaryWombat日期可以是字符串形式,也可以是BC的负数。仅供参考:a)
SimpleDateFormat
将1582-10-15年之前的日期处理为儒略历日期(非常简化的历史模型)。b) 在打印时,使用h而不是h(指定一天中的小时数)的常见错误也可能发生在Java-8-
DateTimeFormatter
上。c) 如果输入是ISO-8601格式,那么解释应该是公历(如Java-8中所做的)。
-125818763400