tl;博士
LocalDate.of( 2014 , 2 , 11 )
如果您坚持使用糟糕的旧 java.util.Date 类,请从现代 java.time 类转换。
java.util.Date // Terrible old legacy class, avoid using. Represents a moment in UTC.
.from( // New conversion method added to old classes for converting between legacy classes and modern classes.
LocalDate // Represents a date-only value, without time-of-day and without time zone.
.of( 2014 , 2 , 11 ) // Specify year-month-day. Notice sane counting, unlike legacy classes: 2014 means year 2014, 1-12 for Jan-Dec.
.atStartOfDay( // Let java.time determine first moment of the day. May *not* start at 00:00:00 because of anomalies such as Daylight Saving Time (DST).
ZoneId.of( "Africa/Tunis" ) // Specify time zone as `Continent/Region`, never the 3-4 letter pseudo-zones like `PST`, `EST`, or `IST`.
) // Returns a `ZonedDateTime`.
.toInstant() // Adjust from zone to UTC. Returns a `Instant` object, always in UTC by definition.
) // Returns a legacy `java.util.Date` object. Beware of possible data-loss as any microseconds or nanoseconds in the `Instant` are truncated to milliseconds in this `Date` object.
详情
如果您想要“简单”,您应该使用 Java 8 中的新 java.time package,而不是 Java 捆绑的臭名昭著的麻烦 java.util.Date 和 .Calendar 类。
java.time
Java 8 中内置的 java.time 框架取代了麻烦的旧 java.util.Date/.Calendar 类。
仅限日期
LocalDate 类由 java.time 提供,用于表示没有任何时间或时区的仅日期值。您确实需要时区来确定日期,例如,巴黎的新一天比蒙特利尔更早。 ZoneId 类用于时区。
ZoneId zoneId = ZoneId.of( "Asia/Singapore" );
LocalDate today = LocalDate.now( zoneId );
转储到控制台:
System.out.println ( "today: " + today + " in zone: " + zoneId );
今天:2015-11-26 在区域:亚洲/新加坡
或者使用工厂方法来指定年月日。
LocalDate localDate = LocalDate.of( 2014 , Month.FEBRUARY , 11 );
本地日期:2014-02-11
或者传递一个月份号 1-12 而不是 DayOfWeek 枚举对象。
LocalDate localDate = LocalDate.of( 2014 , 2 , 11 );
时区
LocalDate 没有实际意义,除非您将其调整为时区。在 java.time 中,我们应用一个时区来生成一个ZonedDateTime 对象。这也意味着一天中的某个时间,但是什么时间呢?通常在一天中的第一刻是有意义的。您可能认为这意味着时间 00:00:00.000,但由于夏令时 (DST) 和其他异常情况,并非总是如此。我们不是假设那个时间,而是要求 java.time 通过调用atStartOfDay 来确定一天中的第一个时刻。
以continent/region 的格式指定proper time zone name,例如America/Montreal、Africa/Casablanca 或Pacific/Auckland。切勿使用 3-4 个字母的缩写,例如 EST 或 IST,因为它们不是真正的时区,没有标准化,甚至不是唯一的(!)。
ZoneId zoneId = ZoneId.of( "Asia/Singapore" );
ZonedDateTime zdt = localDate.atStartOfDay( zoneId );
zdt: 2014-02-11T00:00+08:00[亚洲/新加坡]
UTC
对于后端工作(业务逻辑、数据库、数据存储和交换),我们通常使用UTC 时区。在 java.time 中,Instant 类代表 UTC 时间线上的一个时刻。通过调用toInstant,可以从 ZonedDateTime 中提取 Instant 对象。
Instant instant = zdt.toInstant();
即时:2014-02-10T16:00:00Z
转换
您应该完全避免使用java.util.Date 类。但是,如果您必须与 java.time 尚未更新的旧代码进行互操作,则可以来回转换。寻找添加到旧类的新转换方法。
java.util.Date d = java.util.from( instant ) ;
……和……
Instant instant = d.toInstant() ;
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。 Hibernate 5 & JPA 2.2 支持 java.time。
从哪里获取 java.time 类?
更新:Joda-Time 库现在处于维护模式,并建议迁移到 java.time 类。我将保留此部分以了解历史。
乔达时间
一方面,Joda-Time 使用合理的编号,所以二月是 2 而不是 1。另一件事是,Joda-Time DateTime 真正知道其分配的时区,而 java.util.Date 似乎有时区但没有。
别忘了时区。否则,您将获得 JVM 的默认值。
DateTimeZone timeZone = DateTimeZone.forID( "Asia/Singapore" );
DateTime dateTimeSingapore = new DateTime( 2014, 2, 11, 0, 0, timeZone );
DateTime dateTimeUtc = dateTimeSingapore.withZone( DateTimeZone.UTC );
java.util.Locale locale = new java.util.Locale( "ms", "SG" ); // Language: Bahasa Melayu (?). Country: Singapore.
String output = DateTimeFormat.forStyle( "FF" ).withLocale( locale ).print( dateTimeSingapore );
转储到控制台...
System.out.println( "dateTimeSingapore: " + dateTimeSingapore );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "output: " + output );
运行时……
dateTimeSingapore: 2014-02-11T00:00:00.000+08:00
dateTimeUtc: 2014-02-10T16:00:00.000Z
output: Selasa, 2014 Februari 11 00:00:00 SGT
转化
如果您需要转换为 java.util.Date 以与其他类一起使用...
java.util.Date date = dateTimeSingapore.toDate();