tl;博士
myJavaUtilDate.toInstant()
.atZone( ZoneId.of( "America/Montreal" ) )
.toLocalDate()
.toString()
2017-01-23
日期时间不是字符串
不要将日期时间对象与表示其值的字符串混淆。可以通过解析字符串来创建日期时间对象。日期时间对象可以生成一个字符串来表示其值。但是字符串和日期时间对象是不同的和分开的。因此,日期时间对象没有“格式”。
使用 java.time
您正在使用麻烦的旧日期时间类 (Date & Calendar),它们现在已被 java.time 类所取代。
如果数据源 (Swing) 尚未更新为直接处理 java.time 类型,则进行转换。寻找添加到旧类的新转换方法。
Instant 类表示UTC 中时间轴上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。
Instant instant = myJavaUtilDate.toInstant() ;
instant.toString(): 2017-01-23T06:23:45.678Z
java.util.Date 和 Instant 均采用 UTC。要确定日期,您必须指定时区。对于任何给定的时刻,日期在世界各地因地区而异。例如,法国巴黎午夜过后几分钟是新的一天,而魁北克蒙特利尔仍是“昨天”。
以continent/region 的格式指定proper time zone name,例如America/Montreal、Africa/Casablanca 或Pacific/Auckland。切勿使用 3-4 个字母的缩写,例如 EST 或 IST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ; // Or ZoneId.systemDefault()
ZonedDateTime zdt = instant.atZone( z );
zdt.toString(): 2017-01-23T01:23:45.678+05:00[美国/蒙特利尔]
现在您可以提取仅日期部分。 LocalDate 类表示没有时间和时区的仅日期值。
LocalDate ld = zdt.toLocalDate();
您的问题不清楚您的目标。如果您只想序列化此日期值以供以后比较,请以标准ISO 8601 格式写入文本。 java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。
我建议您尽可能坚持使用标准的 ISO 8601 字符串格式。它们旨在最大程度地减少歧义。它们很容易被机器解析。它们很容易被不同文化的人类阅读。
String output = ld.toString() ;
2017-01-23
如果您确实需要年、月和日的各个部分,请查询LocalDate 对象。与遗留类不同,在 java.time 中,1 月至 12 月的月份编号为 1-12。
int year = ld.getYear() ;
int month = ld.getMonthValue() ;
int dayOfMonth = ld.getDayOfMonth() ;
您还可以将月份作为强大的Month 枚举对象。
Month m = ld.getMonth();
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。