Як створити об’єкт дати зі значеннями в Java


91

Мені потрібен об’єкт дати для дати 11.02.2014. Я не можу безпосередньо створити його таким чином,

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

Отже, я роблю наступне,

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

Чи існує простий спосіб створити об'єкт дати в Java?


7
Що не так просто у вашому підході?
giorashc

3
"Чи є якийсь простий спосіб". Що змушує вас думати, що це не так просто, як може бути? Часи та дати набагато складніші, ніж ви можете подумати. Є кілька календарів і кілька часових поясів.
Raedwald,

5
Один рядок, як Date myDate = new GregorianCalendar(2014, 2, 11).getTime();,?
Елліотт Фріш,

2
Обережно з допомогою ведучого нуля в целочисленном літералі , як показано в цьому питанні, 02. У Java це означає вісімкове (базове-8) число, а не десяткове (базове-10) число.
Василь Бурк

2
FYI, страшенно неприємні старі класи часу та часу, такі як java.util.Date, java.util.Calendarі java.text.SimpleDateFormatтепер є застарілими , витіснені класами java.time, вбудованими в Java 8 та пізніші версії. Див. Підручник Oracle .
Василь Бурк

Відповіді:


108

Потрібно: передача 2 як місяць може дати вам несподіваний результат: в календарі API місяць базується на нулі. 2 насправді означає березень.

Я не знаю, що таке "простий" спосіб, який ви шукаєте, оскільки я вважаю, що користуватися Календарем вже досить просто.

Не забувайте використовувати правильні константи для місяця:

 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. Переключіться на JODA Time або Java Time (він же 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 )
0xJoKe

Вибачте помилку. Хоча я думаю, OP вже знає правильний метод виклику: P
Адріан Шум

Цілком впевнений, що маєш рацію. Але для тих (як я), котрі повинні це шукати щоразу, коли це потрібно, це дратує. Дякую за виправлення :)
0xJoKe

1
return new SimpleDateFormat("yyyy-mm-dd").parse(date) повинно бутиreturn new SimpleDateFormat("yyyy-MM-dd").parse(date)
aks

Хороший улов. Не знаю, чому я зробив таку помилку. Виправлення
Адріан Шум

34

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.time у Java 8, а не горезвісний клопіт java.util.Date & .Calendar, що входять до складу Java.

java.time

Java.time структура , вбудована в Java 8 , а потім витісняє клопітно старі класи 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 );

сьогодні: 26.11.2015 в зоні: Азія / Сінгапур

Або використовуйте заводський метод, щоб вказати рік, місяць, день.

LocalDate localDate = LocalDate.of( 2014 , Month.FEBRUARY , 11 );

localDate: 11.02.2014

Або передайте місяць номер 1-12, а не DayOfWeekоб’єкт перерахування.

LocalDate localDate = LocalDate.of( 2014 , 2 , 11 );

Часовий пояс

введіть тут опис зображення

A LocalDateне має реального значення, поки ви не налаштуєте його на часовий пояс. У java.time ми застосовуємо часовий пояс для генерації ZonedDateTimeоб’єкта. Це також означає час доби, але який час? Зазвичай має сенс піти з першого моменту дня. Можна подумати, що це означає час 00:00:00.000, але не завжди правдивий через перехід на літній час (DST) та, можливо, інші аномалії. Замість того, щоб припустити цей час, ми просимо java.time визначити перший момент дня, зателефонувавши atStartOfDay.

Вкажіть правильний час ім'я зони в форматі continent/region, наприклад 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. Миттєвий об’єкт можна отримати з ZonedDateTime за допомогою виклику 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.Date, Calendar, і SimpleDateFormat.

Щоб дізнатись більше, див. Підручник Oracle . І шукайте в Stack Overflow багато прикладів та пояснень. Специфікація - JSR 310 .

Проект Joda-Time , який зараз перебуває в режимі обслуговування , радить перейти на класи java.time .

Ви можете обмінювати об'єкти java.time безпосередньо з базою даних. Використовуйте драйвер JDBC, сумісний з JDBC 4.2 або новішою. Не потрібні рядки, не потрібні java.sql.*класи. Hibernate 5 та JPA 2.2 підтримують java.time .

Де отримати класи java.time?


ОНОВЛЕННЯ: Бібліотека Joda-Time тепер перебуває в режимі обслуговування та радить перехід на класи java.time . Я залишаю цей розділ на місці історії.

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

4
Лише один коментар. Практика префіксації нулів у таких полях new DateTime( 2014, 02, 11, 0, 0, timeZone );, мабуть, не краща. Хоча це працює в цьому випадку, але він не компілюється для серпня та вересня, якщо ви переходите, 08а 09як префікс int літералу з 0 означає восьмеричну презентацію. Це навіть дасть вам несподівані значення роками раніше 1000, наприклад new DateTime( 0100, 02, 01, 0, 0, timeZone );, можна очікувати, що це буде 100 AD, але насправді це 64 AD
Адріан Шум

@AdrianShum Yikes! Я ніколи не знав, що невинна маленька друкарська помилка, така як провідний нуль у цілочисельному літералі, може мати такий неприємний побічний ефект. Дякую.
Василь Бурк,

2
Шановний виборець, залиште критику разом із своїм голосуванням.
Василь Бурк

Msgstr "Якщо ви наполягаєте на використанні жахливого старого класу java.util.Date". Багато постачальників не пропонують сервери tomcat, які працюють на Java за межами JDK7, тому, хоча я хотів би використовувати нові речі, деякі застрягли в старому лайні через інших .....
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

Y .. І переконайтеся, що ніколи не використовуєте 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();
}

Страшні Calendarта SimpleDateFormatкласи були витіснені роками тому класами java.time . Запропонувати їх використання у 2018 році - погана порада.
Василь Бурк,

Ця відповідь не стосується особливостей цього Питання.
Василь Бурк

1
Під «рівнями API» я припускаю, що ви маєте на увазі Android. Але це не специфічне для Android питання. Крім того, більшість функцій java.time переноситься назад на Java 6 і 7 у проекті ThreeTen-Backport . Подальше адаптоване до Android у проекті ThreeTenABP . Отже, не потрібно ніколи використовувати ці жахливі застарілі класи дати та часу. Заняття 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як у другому рядку. Моя звичка полягає в тому LocalDate.of(2000, Month.JANUARY, 1), що мені стає зрозумілішим читати.
Оле В. В.

і це тому, що відповідь містить декларацію LocalDate, а не лише запитуваний об’єкт Date (не застарілий, а іноді використовується) ...
Адам Сіленко

-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 можна використовувати для форматування дати відповідно до нас. а потім синтаксичний аналіз всередині об'єкта дати. Наведена вище програма показує, як отримати дні тижня, вказавши будь-яку дату.
Анкуш,

-5

Я думаю, що ваша дата походить від php і записується в html (dom) чи? У мене є php-функція для підготовки всіх дат та позначок часу. Це повертає необхідну форму.

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

цей формат можна використовувати на js для створення нової дати ...

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

Що я скажу, зробіть свою власну функцію, яка полегшить ваше життя. Ви можете використати мій функціонал як зразок, але включений до мого 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
Чому ви відповідаєте на> 2-річне запитання про Java відповіддю на PHP?
Алан Хей
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.