在爪哇的奇怪约会
以下 Java 代码仅使用 SimpleDateFormat
解析日期(带有时间部分)2009-01-28-09:11:12
。我们来看看吧。
final public class Main
{
public static void main(String[] args)
{
try
{
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
Date d = df.parse("2009-01-28-09:11:12");
System.out.println(d);
}
catch (ParseException ex)
{
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
上述代码(解析后)显示的日期(带时间)如下。
Sun Nov 30 22:07:51 IST 2008
即使我们尝试解析日期 2009-01-28-09:11:12
, 看起来有些古怪。为什么会这样解析呢?
The following Java code just parses a date (with time portion) 2009-01-28-09:11:12
using SimpleDateFormat
. Let's have look at it.
final public class Main
{
public static void main(String[] args)
{
try
{
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
Date d = df.parse("2009-01-28-09:11:12");
System.out.println(d);
}
catch (ParseException ex)
{
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
The date (with time) displayed (after parsing) by the above code is as follows,
Sun Nov 30 22:07:51 IST 2008
even though we are attempting to parse the date 2009-01-28-09:11:12
. It looks somewhat wonky. Why does it parse so?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的日期格式不应该是这样的:
以匹配此格式:
?
至于为什么,按照这个:
解析器实际上将这些视为数字,技巧在于 - 是数字的一部分,代表负数。因此,如果您这样做:
它会给出:
将 2009 解析为 yyyy,然后将 -0 解析为 MM(这是上个月,因为月份从 1 开始),然后将 1 解析为 dd,等等。
按照 DateFormat 中的解析:
我想,如果您有选择的话,如果您喜欢 2009/01/02 12:34:56 等格式,最好使用斜杠而不是破折号。这:
会抛出异常:
我只能得出结论,
/
不被 DateFormat 视为数字除法是一件非常好的事情...Shouldn't your date format be something like this:
to match this format:
?
As for why, per this:
the parser actually looks at these as numbers, and the trick is that - is a part of a number, representing negative numbers. So if you do:
it gives:
That parses 2009 as yyyy, then -0 as MM (which is previous month as months start from 1), then 1 as dd, etc.
As per parse in DateFormat:
I guess, if you have an option, it would be better to use slashes instead of dashes, if you like formats like 2009/01/02 12:34:56. This:
will throw an exception:
I can only conclude it's a very good thing that
/
is not considered a number division by DateFormat...好吧,您可以定义您实际正在解析的格式...
Well, you could define the format that you actually are parsing...
默认情况下以宽松模式解析日期。这意味着如果不是闰年,它会容忍诸如将 2 月 29 日解析为 3 月 1 日之类的错误。您要求它解析的是 2009 年 1 月 28 日,它会尽职尽责地尝试准确地提供您所要求的内容。
要关闭此行为,请调用 format.setLenient(false)。然后,如果您尝试解析不是真实日期的内容,则日期格式将引发异常。
The dates are parsed in lenient mode by default. This means that it's forgiving to errors like parsing feb 29 as mar 1 if it's not a leap year. What you are asking it to parse is the -28th day of the -1st month of 2009, and it dutifully tries to give you exactly what you ask for.
To turn off this behaviour call format.setLenient(false). Then the dateformat will throw an exception if you try to parse something that's not a real date.
tl;dr
如果您必须为数据使用自定义格式而不是标准格式,请定义与 java.time.format.DateTimeFormatter 匹配的格式化模式,以解析为 java.time.LocalDateTime 对象。
避免遗留类
您正在使用有严重缺陷的遗留类,这些遗留类已被 Java 8+ 的 JSR 310 中定义的现代 java.time 类所取代。
切勿使用
Date
、Calendar
、Timestamp
、SimpleDateFormat
等。java.time
DateTimeFormatter
定义格式模式以匹配您的非标准格式。实例化
DateTimeFormatter
对象。LocalDateTime
要表示带有当天时间但缺少时区上下文或相对于 UTC 的偏移量的日期,请使用
java.time.LocalDateTime
。ISO 8601
ISO 8601 是文本日期时间格式的国际标准。
不要发明自己的格式,而应使用 ISO 8601。日期的标准格式在日期部分和日期部分之间使用
T
时间部分。java.time 类在解析/生成文本时默认使用 ISO 8601 格式。
解析:
生成:
tl;dr
If you must use a custom format for your data rather than a standard format, define a formatting pattern to match with
java.time.format.DateTimeFormatter
to parse into ajava.time.LocalDateTime
object.Avoid legacy classes
You are using terribly-flawed legacy classes that were supplanted by the modern java.time classes defined in JSR 310 for Java 8+.
Never use
Date
,Calendar
,Timestamp
,SimpleDateFormat
, etc.java.time
DateTimeFormatter
Define a formatting pattern to match your non-standard format. Instantiate a
DateTimeFormatter
object.LocalDateTime
To represent a date with time-of-day but lacking the context of a time zone or offset-from-UTC, use
java.time.LocalDateTime
.ISO 8601
ISO 8601 is an international standard of date-time formats in text.
Rather than invent your own format, use ISO 8601. The standard format for your date uses a
T
between the date portion and the time portion.The java.time classes use ISO 8601 formats by default when parsing/generating text.
Parsing:
Generating: