如何在java中创建具有值的日期对象tl;博士详java.time关于 java.time 城大时间

2022-08-31 08:34:46

我需要日期对象的日期 2014-02-11.我不能直接像这样创建它,

Date myDate = new Date(2014, 02, 11);

所以我正在做如下,

Calendar myCalendar = new GregorianCalendar(2014, 2, 11);
Date myDate = myCalendar.getTime();

有没有简单的方法可以在java中创建日期对象?


答案 1

Gotcha:将 2 作为月份传递可能会给你意想不到的结果:在日历 API 中,月份是从零开始的。2 实际上意味着 3 月。

我不知道您正在寻找的“简单”方式是什么,因为我觉得使用日历已经足够简单了。

请记住对月份使用正确的常量:

 Date date = new GregorianCalendar(2014, Calendar.FEBRUARY, 11).getTime();

另一种方法是使用DateFormat,我通常有一个这样的实用程序:

 public static Date parseDate(String date) {
     try {
         return new SimpleDateFormat("yyyy-MM-dd").parse(date);
     } catch (ParseException e) {
         return null;
     }
  }

这样我就可以简单地写

Date myDate = parseDate("2014-02-14");

我更喜欢的另一种选择:不再使用Java Date/Calendar。切换到 JODA 时间或 Java 时间(也称为 JSR310,在 JDK 8+ 中可用)。您可以使用来表示日期,该日期可以通过以下方式轻松创建LocalDate

LocalDate myDate =LocalDate.parse("2014-02-14");
// or
LocalDate myDate2 = new LocalDate(2014, 2, 14);
// or, in JDK 8+ Time
LocalDate myDate3 = LocalDate.of(2014, 2, 14);

答案 2

tl;博士

LocalDate.of( 2014 , 2 , 11 )

如果你坚持使用可怕的旧类,请从现代java.time类转换。java.util.Date

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包,而不是臭名昭着的麻烦java.util.Date& 。与 Java 捆绑在一起的日历类。

java.time

Java 8 和后来的 java.time 框架取代了麻烦的旧 java.util.Date/。日历类。

仅日期

enter image description here

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 );

时区

enter image description here

A 在调整为时区之前没有实际意义。在java.time中,我们应用时区来生成对象。这也意味着一天中的时间,但什么时间呢?通常,与一天中的第一刻一起去是有意义的。您可能认为这意味着时间,但由于夏令时(DST)和其他异常情况,并不总是正确的。我们没有假设那个时间,而是要求java.time通过调用StartOfDay来确定一天中的第一刻。LocalDateZonedDateTime00:00:00.000

以 的格式指定适当的时区名称,例如 美国/蒙特利尔非洲/卡萨布兰卡或 。切勿使用3-4个字母的缩写,例如或因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。continent/regionPacific/AucklandESTIST

ZoneId zoneId = ZoneId.of( "Asia/Singapore" );
ZonedDateTime zdt = localDate.atStartOfDay( zoneId );

zdt: 2014-02-11T00:00+08:00[亚洲/新加坡]

世界协调时

enter image description here

对于后端工作(业务逻辑,数据库,数据存储和交换),我们通常使用UTC时区。在 java.time 中,Instant 类以 UTC 格式表示时间轴上的某个时刻。可以通过调用 Instant 从 ZonedDateTime 中提取 Instant 对象。

Instant instant = zdt.toInstant();

即时: 2014-02-10T16:00:00Z

转换

应完全避免使用类。但是,如果您必须与尚未针对 java.time 更新的旧代码进行互操作,则可以来回转换。查看添加到旧类中的新转换方法。java.util.Date

java.util.Date d = java.util.from( instant ) ;

...和。。。

Instant instant = d.toInstant() ;

Java 中所有日期时间类型(包括新式和旧版)的表


关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧日期时间类,如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要类。Hibernate 5 & JPA 2.2 支持 java.timejava.sql.*

从哪里获取 java.time 类?


更新:Joda-Time 库现在处于维护模式,建议迁移到 java.time 类。我将这一部分留给历史。

城大时间

首先,Joda-Time使用合理的编号,因此二月不是 。另一件事,Joda-Time DateTime真正知道其分配的时区,这与java.util.Date不同,java.util.Date似乎有时区但没有。21

不要忘记时区。否则,您将获得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();