Jak utworzyć obiekt daty z wartościami w java

91

Potrzebuję obiektu daty na dzień 2014-02-11. Nie mogę tego bezpośrednio stworzyć w ten sposób,

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

Więc robię jak następuje,

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

Czy istnieje łatwy sposób na utworzenie obiektu daty w Javie?

Banukobhan Nagendram
źródło
7
Co nie jest łatwe w Twoim podejściu?
giorashc
3
„Czy jest jakiś łatwy sposób”. Dlaczego myślisz, że nie jest to tak łatwe, jak to tylko możliwe? Godziny i daty są znacznie bardziej skomplikowane, niż mogłoby się wydawać. Istnieje wiele kalendarzy i wiele stref czasowych.
Raedwald,
5
Jedna linia, na przykład Date myDate = new GregorianCalendar(2014, 2, 11).getTime();?
Elliott Frisch
2
Strzeżcie stosując zero w dosłownym całkowitej, jak widać na to pytanie 02. W Javie oznacza to liczbę ósemkową (podstawa-8) zamiast liczby dziesiętnej (podstawa-10).
Basil Bourque
2
FYI, strasznie kłopotliwe stare klasy daty i czasu, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą teraz starsze , zastąpione przez klasy java.time wbudowane w Javę 8 i nowsze. Zobacz samouczek firmy Oracle .
Basil Bourque

Odpowiedzi:

108

Rozumiem: zaliczenie 2 w miesiącu może dać nieoczekiwany wynik: w Calendar API miesiąc jest liczony od zera. 2 faktycznie oznacza marzec.

Nie wiem, jaki jest „łatwy” sposób, którego szukasz, ponieważ uważam, że korzystanie z Kalendarza jest już wystarczająco łatwe.

Pamiętaj, aby używać odpowiednich stałych dla miesiąca:

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

Innym sposobem jest użycie DateFormat, którego zwykle używam w następujący sposób:

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

abym mógł po prostu pisać

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

Jeszcze inna alternatywa, którą preferuję: Nie używaj już daty / kalendarza Java. Przełącz się na czas JODA lub czas Java (znany również jako JSR310, dostępny w JDK 8+). Możesz użyć LocalDatedo przedstawienia daty, którą można łatwo utworzyć za pomocą

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);
Adrian Shum
źródło
1
.toTime()nie istnieje. Powinno być .getTime()(patrz Java Docs )
0xJoKe
Przepraszam za literówkę. Chociaż myślę, że OP zna już poprawną metodę dzwonienia: P
Adrian Shum
Jestem pewien, że masz rację. Ale dla tych (takich jak ja), którzy muszą to sprawdzić za każdym razem, gdy jest to potrzebne, jest to denerwujące. Dzięki za naprawienie :)
0xJoKe
1
return new SimpleDateFormat("yyyy-mm-dd").parse(date) powinno byćreturn new SimpleDateFormat("yyyy-MM-dd").parse(date)
aks
Dobry chwyt. Nie wiem, dlaczego popełniłem taki błąd. Naprawianie tego
Adrian Shum
34

tl; dr

LocalDate.of( 2014 , 2 , 11 )

Jeśli nalegasz na używanie okropnej starej java.util.Dateklasy, przekonwertuj ją z nowoczesnych klas 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.   

Detale

Jeśli chcesz „łatwego”, powinieneś używać nowego pakietu java.time w Javie 8 zamiast notorycznie kłopotliwych klas java.util.Date i .Calendar dołączonych do Javy.

java.time

Java.time ramy wbudowany w Java 8 i później wypiera kłopotliwe starych klas java.util.Date/.Calendar.

Tylko data

wprowadź opis obrazu tutaj

LocalDateKlasa jest oferowana przez java.time reprezentować wartości daty-tylko bez time-of-day lub strefy czasowej. Do ustalenia daty potrzebna jest strefa czasowa, ponieważ nowy dzień zaczyna się wcześniej w Paryżu niż na przykład w Montrealu. ZoneIdKlasa jest dla stref czasowych.

ZoneId zoneId = ZoneId.of( "Asia/Singapore" );
LocalDate today = LocalDate.now( zoneId );

Zrzuć na konsolę:

System.out.println ( "today: " + today + " in zone: " + zoneId );

dzisiaj: 26.11.2015 w strefie: Azja / Singapur

Lub użyj metody fabrycznej, aby określić rok, miesiąc, dzień.

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

localDate: 2014-02-11

Lub podaj miesiąc numer 1-12 zamiast DayOfWeekobiektu wyliczenia.

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

Strefa czasowa

wprowadź opis obrazu tutaj

A LocalDatenie ma prawdziwego znaczenia, dopóki nie dostosujesz go do strefy czasowej. W java.time do wygenerowania ZonedDateTimeobiektu stosujemy strefę czasową . Oznacza to również porę dnia, ale o której godzinie? Zwykle warto iść na pierwszą chwilę dnia. Możesz pomyśleć, że oznacza to godzinę 00:00:00.000, ale nie zawsze jest to prawdą z powodu czasu letniego (DST) i być może innych anomalii. Zamiast zakładać ten czas, prosimy java.time o określenie pierwszej chwili dnia przez telefon atStartOfDay.

Określ prawidłową nazwę strefy czasowej w formacie continent/region, takie jak America/Montreal, Africa/Casablancalub Pacific/Auckland. Nigdy nie używaj 3-4-literowego skrótu, takiego jak ESTlub, ISTponieważ nie są to prawdziwe strefy czasowe, nie są standaryzowane, a nawet nie są unikalne (!).

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

zdt: 2014-02-11T00: 00 + 08: 00 [Azja / Singapur]

UTC

wprowadź opis obrazu tutaj

Do pracy na zapleczu (logika biznesowa, baza danych, przechowywanie i wymiana danych) zwykle używamy strefy czasowej UTC . W java.time Instantklasa reprezentuje moment na osi czasu w UTC. Obiekt Instant można wyodrębnić z ZonedDateTime przez wywołanie toInstant.

Instant instant = zdt.toInstant();

natychmiastowy: 2014-02-10T16: 00: 00Z

Konwertować

Należy java.util.Datecałkowicie unikać używania klasy. Ale jeśli musisz współdziałać ze starym kodem, który nie został jeszcze zaktualizowany dla java.time , możesz konwertować tam iz powrotem. Spójrz na nowe metody konwersji dodane do starych klas.

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

…i…

Instant instant = d.toInstant() ;

Tabela wszystkich typów dat i godzin w Javie, zarówno nowoczesnych, jak i starszych


Informacje o java.time

Struktura java.time jest wbudowana w Javę 8 i nowsze. Klasy te kłopotliwe zastąpić stary starszych klas Date-Time, takich jak java.util.Date, Calendar, i SimpleDateFormat.

Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj Stack Overflow, aby znaleźć wiele przykładów i wyjaśnień. Specyfikacja to JSR 310 .

Projekt Joda-Time , obecnie w trybie konserwacji , zaleca migrację do klas java.time .

Możesz wymieniać obiekty java.time bezpośrednio ze swoją bazą danych. Użyj sterownika JDBC zgodnego z JDBC 4.2 lub nowszym. Nie ma potrzeby stosowania ciągów ani java.sql.*klas. Hibernate 5 i JPA 2.2 obsługują java.time .

Skąd wziąć klasy java.time?


AKTUALIZACJA: Biblioteka Joda-Time jest teraz w trybie konserwacji i zaleca migrację do klas java.time . Zostawiam tę sekcję na miejscu dla historii.

Joda-Time

Po pierwsze, Joda-Time używa rozsądnej numeracji, więc luty 2nie 1. Inna sprawa, Joda-Time DateTime naprawdę zna swoją przypisaną strefę czasową w przeciwieństwie do java.util.Date, który wydaje się mieć strefę czasową, ale jej nie ma.

I nie zapomnij o strefie czasowej. W przeciwnym razie otrzymasz domyślną maszynę 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 );

Zrzuć na konsolę…

System.out.println( "dateTimeSingapore: " + dateTimeSingapore );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "output: " + output );

Po uruchomieniu…

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

Konwersja

Jeśli musisz przekonwertować na java.util.Date do użytku z innymi klasami…

java.util.Date date = dateTimeSingapore.toDate();
Basil Bourque
źródło
4
Tylko jeden komentarz. Praktyka dodawania przedrostków zer w polach takich jak new DateTime( 2014, 02, 11, 0, 0, timeZone );prawdopodobnie nie jest preferowana. Chociaż działa w tym przypadku, ale nie skompiluje się w sierpniu i wrześniu, jeśli przechodzisz 08i 09jako prefiks int literału z 0 oznacza prezentację ósemkową. Da ci to nawet nieoczekiwane wartości na lata wcześniej 1000, np. new DateTime( 0100, 02, 01, 0, 0, timeZone );Można się spodziewać, że będzie to 100 AD, ale w rzeczywistości jest to 64 AD
Adrian Shum
@AdrianShum Yikes! Nigdy nie wiedziałem, że niewinna mała literówka, taka jak wiodące zero w literale całkowitym, może mieć tak paskudny efekt uboczny. Dzięki.
Basil Bourque
2
Szanowny Głosowco, zostaw krytykę wraz ze swoim głosem.
Basil Bourque
„Jeśli nalegasz na używanie okropnej starej klasy java.util.Date”. Wielu dostawców nie oferuje serwerów Tomcat, które działają w Javie poza JDK7, więc chociaż wolałbym używać nowszych rzeczy, niektórzy utknęli w starym gównie z powodu innych .....
KimvdLinde
@KimvdLinde Przeczytaj uważniej moją odpowiedź. Spójrz na kule. Znajdź słowa „Java SE 6 i Java SE 7”.
Basil Bourque
14

Myślę, że najlepszym sposobem byłoby użycie SimpleDateFormatprzedmiotu.

DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String dateString = "2014-02-11";
Date dateObject = sdf.parse(dateString); // Handle the ParseException here
edubriguenti
źródło
Y .. I pamiętaj, aby nigdy nie używać YYYY - użyj yyyy - zwłaszcza jeśli robisz to w odwrotnej kolejności z formatem zamiast parsowania. Otrzymujesz dziwne wyniki !!! Zobacz tutaj: code.sololearn.com/c0EYUAOc92uQ/#java
JGFMK
9

Z Java8:

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

Date date = Date.from(Instant.parse("2000-01-01T00:00:00.000Z"))
Tody.Lu
źródło
2

Spróbuj tego

 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();
Selva
źródło
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();
}
Syed Danish Haider
źródło
Klasy straszne Calendari SimpleDateFormatzostały zastąpione lata temu przez klasy java.time . Sugerowanie ich użycia w 2018 roku to kiepska rada.
Basil Bourque
Ta odpowiedź nie odnosi się do szczegółów tego pytania.
Basil Bourque
1
Zakładam, że przez „poziomy API” masz na myśli Androida. Ale to nie jest pytanie dotyczące Androida. Co więcej, większość funkcjonalności java.time jest przenoszona z powrotem do Java 6 i 7 w projekcie ThreeTen-Backport . Dalsze dostosowanie do Androida w projekcie ThreeTenABP . Nie ma więc potrzeby używania tych okropnych, starszych klas daty i czasu. W java.time zajęcia są radykalnie lepsze.
Basil Bourque
Dzięki za ten komentarz. Czy ta biblioteka zapewnia takie funkcje, jak różnica dat i różnice czasu.
Syed Danish Haider
1
Tak. Search Stack Overflow dla wielu istniejących pytań i odpowiedzi na ten temat. Zobacz też projekt ThreeTen-Extra (nie przeniesiony na wczesny Android).
Basil Bourque
0

Najprostsze sposoby:

Date date = Date.valueOf("2000-1-1");
LocalDate localdate = LocalDate.of(2000,1,1);
LocalDateTime localDateTime = LocalDateTime.of(2000,1,1,0,0);
Adam Silenko
źródło
Pierwszego należy unikać, ponieważ java.sql.Dateklasa, której używasz, jest źle zaprojektowana i dawno przestarzała. Polecam LocalDatejak w drugiej linii. Mój zwyczaj jest taki LocalDate.of(2000, Month.JANUARY, 1), że czytanie jest dla mnie nieco jaśniejsze.
Ole VV
a to dlatego, że odpowiedź zawiera deklarację LocalDate, a nie tylko pytany obiekt Date (nie jest przestarzały i czasami używany) ...
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));
    }
}
Ankush
źródło
Formater SimpleDateFormat może służyć do formatowania daty według nas. a następnie analizowanie wewnątrz obiektu Date. Powyższy program pokazuje, jak uzyskać dni tygodnia, podając dowolną datę.
Ankush
-5

Myślę, że twoja data pochodzi z php i jest zapisana w html (dom) lub? Mam funkcję php do przygotowania wszystkich dat i znaczników czasu. To zwraca formację, która jest potrzebna.

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

ten format może być używany w js do tworzenia nowej daty ...

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

Powiem tylko: stwórz własną funkcję do owinięcia, która ułatwi ci życie. Możesz użyć mojej funkcji jako próbki, ale jest zawarta w moich cms, nie możesz skopiować i wkleić 1 do 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();
}
Paykoman
źródło
2
Dlaczego odpowiadasz na pytanie Java sprzed ponad 2 lat, udzielając odpowiedzi w języku PHP?
Alan Hay,