如何在Java中使用值创建日期对象


91

我需要一个日期对象作为日期2014-02-11。我不能像这样直接创建它,

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

所以我在做如下

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

有什么简单的方法可以在Java中创建日期对象?


7
您的方法有何难处?
giorashc 2014年

3
“有没有简单的方法”。是什么让您认为这并不那么容易?时间和日期比您想象的要复杂得多。有多个日历和多个时区。
2014年

5
一行像Date myDate = new GregorianCalendar(2014, 2, 11).getTime();
Elliott Frisch 2014年

2
提防在本题中看到的整数文字中使用前导零02。在Java中,这表示八进制数(以8为底)而不是十进制数(以10为底)。
罗勒·布尔克

2
仅供参考,非常麻烦旧日期,时间类,如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat现在的遗产,由取代java.time内置到Java 8和更高等级。请参见Oracle教程
罗勒·布尔克

Answers:


108

陷阱:将2当作月份传递可能会给您带来意想不到的结果:在Calendar API中,月份从零开始。2实际上表示三月。

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

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

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

另一种方法是利用DateFormat,我通常会有这样的util:

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

1
.toTime()不存在。应该是.getTime()(请参阅Java Docs
0xJoKe 2015年

对不起错字了。虽然我认为OP已经知道调用该方法的正确方法:P
Adrian Shum 2015年

很确定你是对的。但是对于那些每次都需要查找它的人(如我)来说,这很烦人。感谢您修复:)
0xJoKe 2015年

1
return new SimpleDateFormat("yyyy-mm-dd").parse(date) 应该是return new SimpleDateFormat("yyyy-MM-dd").parse(date)
aks 2016年

接得好。邓诺为什么我犯了这样的错误。修复问题
Adrian Shum

34

tl; dr

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包,而不是与Java捆绑在一起的麻烦的java.util.Date和.Calendar类。

java.time

java.timeJava 8和更高版本中内置框架取代了麻烦的旧java.util.Date/.Calendar类。

仅日期

在此处输入图片说明

LocalDatejava.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除非您将其调整到一个时区,否则A才具有实际意义。在java.time中,我们应用时区来生成ZonedDateTime对象。那也意味着一天中的某个时间,但是什么时间呢?通常,从一天的第一刻开始就有意义。您可能认为这意味着时间00:00:00.000,但由于夏时制(DST)以及其他异常情况,并非总是如此。而不是假设该时间,我们要求java.time通过调用来确定一天的第一时刻atStartOfDay

指定适当的时区名称,格式continent/region,如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用3-4字母的缩写,例如EST或,IST因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

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

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

世界标准时间

在此处输入图片说明

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

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中所有日期和时间类型的表,包括现代的和传统的


关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

要了解更多信息,请参见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使用明智的编号,因此February2并非如此1。另一件事,与java.util.Date不同,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();

4
只是一条评论。在像这样的字段中添加零前缀的做法new DateTime( 2014, 02, 11, 0, 0, timeZone );可能不是可取的。虽然它的工作原理在这种情况下,但是,它不会编译八月和九月,如果你是路过08,并09为前缀与0表示八进制呈现一个int文字。它甚至会为您提供多年之前的意外值1000,例如new DateTime( 0100, 02, 01, 0, 0, timeZone );,您可能期望它是100AD,但实际上是64AD
Adrian Shum

@AdrianShum Yikes!我从来不知道像整数字面量前导零这样的无辜小错字会产生如此讨厌的副作用。谢谢。
罗勒·布尔克

2
尊敬的唐纳德·沃特(Dear Down-Voter),请在投票时提出批评。
罗勒·布尔克

“如果您坚持使用可怕的旧java.util.Date类”。许多提供程序都没有提供在Java以外的JDK7之上运行的tomcat服务器,因此,尽管我倾向于使用更新的东西,但由于其他原因,有些人陷入了旧局....
KimvdLinde

@KimvdLinde更仔细地阅读我的答案。看子弹。找到单词“ Java SE 6和Java SE 7”。
罗勒·布尔克

14

我认为最好的方法是使用SimpleDateFormat对象。

DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String dateString = "2014-02-11";
Date dateObject = sdf.parse(dateString); // Handle the ParseException here

是的。请确保永远不要使用YYYY-使用yyyy-尤其是如果使用格式而不是解析来反向执行此操作。您得到一些奇怪的结果!!!看到这里:code.sololearn.com/c0EYUAOc92uQ/#java
JGFMK

9

从Java8:

import java.time.Instant;
import java.util.Date;

Date date = Date.from(Instant.parse("2000-01-01T00:00:00.000Z"))

2

试试这个

 Calendar cal = Calendar.getInstance();
    Date todayDate = new Date();
    cal.setTime(todayDate);

    // Set time fields to zero
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    todayDate = cal.getTime();

1
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy HH:mm:ss", Locale.ENGLISH);
//format as u want

try {
    String dateStart = "June 14 2018 16:02:37";
    cal.setTime(sdf.parse(dateStart));
    //all done
} catch (ParseException e) {
    e.printStackTrace();
}

可怕的CalendarSimpleDateFormat类在几年前被java.time类所取代。建议在2018年使用它们是不好的建议。
罗勒·布尔克

该答案未解决此问题的细节。
罗勒·布尔克

1
通过“ API级别”,我假设您的意思是Android。但这不是特定于Android的问题。此外,在ThreeTen-Backport项目中,大多数java.time功能都被反向移植到Java 6和7 。在ThreeTenABP项目中进一步适用于Android 。因此,无需使用那些糟糕的旧式日期时间类。该java.time类是从根本上更好。
罗勒·布尔克

感谢您的评论。此库提供日期差和时间差等功能吗?
Syed Danish Haider

1
是。在“堆栈溢出”中搜索有关此主题的许多现有问与答。并且也可以查看ThreeTen-Extra项目(未反向移植到早期的Android)。
罗勒·布尔克

0

最简单的方法:

Date date = Date.valueOf("2000-1-1");
LocalDate localdate = LocalDate.of(2000,1,1);
LocalDateTime localDateTime = LocalDateTime.of(2000,1,1,0,0);

一个人应该避免第一个,因为java.sql.Date您使用的课程设计不佳且过时了。我建议LocalDate在第二行中使用as。我的习惯是LocalDate.of(2000, Month.JANUARY, 1),我觉得阅读起来更清楚了。
Ole VV

那是因为答案包含LocalDate声明,不仅问了Date对象(不建议使用,有时使用)...
Adam Silenko

-1
import java.io.*;
import java.util.*;
import java.util.HashMap;

public class Solution 
{

    public static void main(String[] args)
    {
        HashMap<Integer,String> hm = new HashMap<Integer,String>();
        hm.put(1,"SUNDAY");
        hm.put(2,"MONDAY");
        hm.put(3,"TUESDAY");
        hm.put(4,"WEDNESDAY");
        hm.put(5,"THURSDAY");
        hm.put(6,"FRIDAY");
        hm.put(7,"SATURDAY");
        Scanner in = new Scanner(System.in);
        String month = in.next();
        String day = in.next();
        String year = in.next();

        String format = year + "/" + month + "/" + day;
        Date date = null;
        try
        {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
            date = formatter.parse(format);
        }
        catch(Exception e){
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
        System.out.println(hm.get(dayOfWeek));
    }
}

SimpleDateFormat格式化程序可用于根据我们格式化日期。然后在Date对象中进行解析。上面的程序显示了如何通过给出任何日期来获得工作日。
Ankush

-5

我认为您的日期来自php,是写入html(dom)还是?我有一个php函数来准备所有日期和时间戳。这将返回所需的队形。

$timeForJS = timeop($datetimeFromDatabase['payedon'], 'js', 'local'); // save 10/12/2016 09:20 on var

这种格式可以在js上使用以创建新的Date ...

<html>
   <span id="test" data-date="<?php echo $timeForJS; ?>"></span>
   <script>var myDate = new Date( $('#test').attr('data-date') );</script>
</html>

我要说的是,使您自己的函数包装起来,使您的生活更轻松。您可以将我的func作为样本,但包含在我的cms中,您不能1对1复制并粘贴:)

    function timeop($utcTime, $for, $tz_output = 'system')
{
    // echo "<br>Current time ( UTC ): ".$wwm->timeop('now', 'db', 'system');
    // echo "<br>Current time (USER): ".$wwm->timeop('now', 'db', 'local');
    // echo "<br>Current time (USER): ".$wwm->timeop('now', 'D d M Y H:i:s', 'local');
    // echo "<br>Current time with user lang (USER): ".$wwm->timeop('now', 'datetimes', 'local');

    // echo '<br><br>Calculator test is users timezone difference != 0! Tested with "2014-06-27 07:46:09"<br>';
    // echo "<br>Old time (USER -> UTC): ".$wwm->timeop('2014-06-27 07:46:09', 'db', 'system');
    // echo "<br>Old time (UTC -> USER): ".$wwm->timeop('2014-06-27 07:46:09', 'db', 'local');

    /** -- */
    // echo '<br><br>a Time from db if same with user time?<br>';
    // echo "<br>db-time (2019-06-27 07:46:09) time left = ".$wwm->timeleft('2019-06-27 07:46:09', 'max');
    // echo "<br>db-time (2014-06-27 07:46:09) time left = ".$wwm->timeleft('2014-06-27 07:46:09', 'max', 'txt');

    /** -- */
    // echo '<br><br>Calculator test with other formats<br>';
    // echo "<br>2014/06/27 07:46:09: ".$wwm->ntimeop('2014/06/27 07:46:09', 'db', 'system');

    switch($tz_output){
        case 'system':
            $tz = 'UTC';
            break;

        case 'local':
            $tz = $_SESSION['wwm']['sett']['tz'];
            break;

        default:
            $tz = $tz_output;
            break;
    }

    $date = new DateTime($utcTime,  new DateTimeZone($tz));

    if( $tz != 'UTC' ) // Only time converted into different time zone
    {
        // now check at first the difference in seconds
        $offset = $this->tz_offset($tz);
        if( $offset != 0 ){
            $calc = ( $offset >= 0  ) ? 'add' : 'sub';
            // $calc = ( ($_SESSION['wwm']['sett']['tzdiff'] >= 0 AND $tz_output == 'user') OR ($_SESSION['wwm']['sett']['tzdiff'] <= 0 AND $tz_output == 'local') ) ? 'sub' : 'add';
            $offset = ['math' => $calc, 'diff' => abs($offset)];
            $date->$offset['math']( new DateInterval('PT'.$offset['diff'].'S') ); // php >= 5.3 use add() or sub()
        }
    }

    // create a individual output
    switch( $for ){
        case 'js':
            $format = 'm/d/Y H:i'; // Timepicker use only this format m/d/Y H:i without seconds // Sett automatical seconds default to 00
            break;
        case 'js:s':
            $format = 'm/d/Y H:i:s'; // Timepicker use only this format m/d/Y H:i:s with Seconds
            break;
        case 'db':
            $format = 'Y-m-d H:i:s'; // Database use only this format Y-m-d H:i:s
            break;
        case 'date':
        case 'datetime':
        case 'datetimes':
            $format = wwmSystem::$languages[$_SESSION['wwm']['sett']['isolang']][$for.'_format']; // language spezific output
            break;
        default:
            $format = $for;
            break;
    }

    $output = $date->format( $format );

    /** Replacement
     * 
     * D = day short name
     * l = day long name
     * F = month long name
     * M = month short name
     */
    $output = str_replace([
        $date->format('D'),
        $date->format('l'),
        $date->format('F'),
        $date->format('M')
    ],[
        $this->trans('date', $date->format('D')),
        $this->trans('date', $date->format('l')),
        $this->trans('date', $date->format('F')),
        $this->trans('date', $date->format('M'))
    ], $output);

    return $output; // $output->getTimestamp();
}

2
为什么用PHP回答2年以上的Java问题?
艾伦·海伊
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.