Java Timestamp - Jak mogę utworzyć znacznik czasu z datą 23/09/2007?

Odpowiedzi:

154

Przez Timestamp, jak sądzę masz na myśli java.sql.Timestamp. Zauważysz, że ta klasa ma konstruktor akceptujący longargument. Możesz przeanalizować to za pomocą DateFormatklasy:

DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
Date date = dateFormat.parse("23/09/2007");
long time = date.getTime();
new Timestamp(time);
Adam Paynter
źródło
1
Normalny format daty ISO to rrrr-MM-dd, poza tym świetnie!
vidstige
1
nowy znacznik czasu (czas); podając błąd, że żaden konstruktor taki jak ten, który ma długą wartość :(
Bhanu Sharma
1
@Bhanu Dokumenty pokazują, że to zajmuje dużo czasu i wydaje się działać poprawnie: docs.oracle.com/javase/7/docs/api/java/sql/…
Hazok,
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
121

A co z tym?

java.sql.Timestamp timestamp = java.sql.Timestamp.valueOf("2007-09-23 10:10:10.0");
pigouina
źródło
1
Timestamp timestamp = Timestamp.valueOf ("2007-09-23 10: 10: 10.0"); zilustrowano metodę valueOf jest zdefiniowana dla typu znacznika czasu jdk 7
Ashish Ratan
nowy znacznik czasu (czas); dając błąd, że żaden konstruktor taki jak ten, który przyjmuje wartość ciągu :(
Bhanu Sharma
@Bhanu Konstruktor zajmuje czas uniksowy w milisekundach. Użyj statycznej metody valueOf, jeśli chcesz uzyskać znacznik czasu z ciągu.
Hazok,
4
Wydaje się, że jest to najlepsza odpowiedź na to pytanie.
Hazok,
1
Najlepszą odpowiedzią jest data, która jest przestarzała, jest złą praktyką jej używania. Ta odpowiedź jest lepsza. Dziękuję
Alberici
18

Co masz na myśli znacznik czasu? Jeśli masz na myśli milisekundy od epoki Uniksa:

GregorianCalendar cal = new GregorianCalendar(2007, 9 - 1, 23);
long millis = cal.getTimeInMillis();

Jeśli chcesz mieć rzeczywisty obiekt java.sql.Timestamp:

Timestamp ts = new Timestamp(millis);
Matthew Flaschen
źródło
2
ŹLE i nie można się skompilować! Błąd kompilacji: 09 jest liczbą ósemkową, ale 9 jest poza zakresem dla ósemek. Błąd logiczny: miesiąc jest od 0, otrzymasz 23 PAŹDZIERNIKA 2007
user85421
Nie mogę otrzymać błędu logicznego, jeśli się nie kompiluje. :) Poważnie, dobre połowy, Carlos. Ósemkowy, który złapałem wcześniej, ale i tak wkleiłem źle. :(
Matthew Flaschen
Właściwie konstruktor Timestamp jest pozbawiony funkcji, ale można użyć metody Timestamp.valueOf ()
Shiva Komuravelly
@ShivaKomuravelly nie wszystkie konstruktory sygnatury czasowej są przestarzałe i przynajmniej nie zajmują wiele milisekund, konstruktor, który przyjmuje datę jako argument, jest przestarzały
brak nazwy
I jest na to stała (zamiast miesiąca = 9):Calendar.SEPTEMBER
Guillaume Husta
12

tl; dr

java.sql.Timestamp.from (
    LocalDate.of ( 2007 , 9 , 23 )
             .atStartOfDay( ZoneId.of ( "America/Montreal" ) )
             .toInstant()
)

java.time

Zaktualizujmy tę stronę, wyświetlając kod przy użyciu java.time wbudowanej w Javę 8 i nowszą.

Te nowe klasy są inspirowane przez Joda-Time , zdefiniowane przez JSR 310 i rozszerzone przez ThreeTen-Extra . Wypierają one notorycznie kłopotliwe stare klasy daty i godziny, dołączane do wczesnych wersji Javy.

W java.time Instantjest moment na osi czasu w UTC. A ZonedDateTimeto natychmiastowa zmiana na strefę czasową ( ZoneId).

Strefa czasowa jest tutaj kluczowa. Daty September 23, 2007nie można przetłumaczyć na moment na osi czasu bez zastosowania strefy czasowej. Weź pod uwagę, że nowy dzień w Paryżu wstaje wcześniej niż w Montrealu, gdzie wciąż jest „wczoraj”.

Ponadto java.sql.Timestamp reprezentuje zarówno datę, jak i godzinę. Musimy więc podać godzinę, która pasuje do daty. Zakładamy, że chcesz, aby pierwsza chwila dnia była porą dnia. Zwróć uwagę, że nie zawsze jest to odpowiednia pora00:00:00.0 powodu czasu letniego i prawdopodobnie innych anomalii.

Zauważ, że w przeciwieństwie do starej klasy java.util.Date iw przeciwieństwie do Joda-Time, typy java.time mają rozdzielczość nanosekund, a nie milisekund. Jest to zgodne z rozdzielczością java.sql.Timestamp.

Zwróć uwagę, że java.sql.Timestamp ma nieprzyjemny zwyczaj niejawnego stosowania bieżącej domyślnej strefy czasowej maszyny JVM do wartości daty i godziny podczas generowania reprezentacji w postaci ciągu za pomocą tej toStringmetody. Tutaj widzisz zastosowaną moją America/Los_Angelesstrefę czasową. Natomiast klasy java.time są bardziej rozsądne i korzystają ze standardowych formatów ISO 8601 .

LocalDate d = LocalDate.of ( 2007 , 9 , 23 ) ;
ZoneId z = ZoneId.of ( "America/Montreal" ) ;
ZonedDateTime zdt = d.atStartOfDay( z ) ;
Instant instant = zdt.toInstant() ;
java.sql.Timestamp ts = java.sql.Timestamp.from ( instant ) ;

Zrzuć na konsolę.

System.out.println ( "d: " + d + " = zdt: " + zdt + " = instant: " + instant + " = ts: " + ts );

Po uruchomieniu.

d: 2007-09-23 = zdt: 2007-09-23T00: 00-04: 00 [Ameryka / Montreal] = natychmiast: 2007-09-23T04: 00: 00Z = ts: 2007-09-22 21:00: 00,0

Nawiasem mówiąc, od wersji JDBC 4.2 można bezpośrednio używać typów java.time. Nie ma potrzeby java.sql.Timestamp.

  • PreparedStatement.setObject
  • ResultSet.getObject

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.

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

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 .

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.

Skąd wziąć klasy java.time?

Projekt ThreeTen-Extra rozszerza java.time o dodatkowe klasy. Ten projekt jest poligonem doświadczalnym dla ewentualnych przyszłych dodatków do java.time. Można znaleźć kilka przydatnych klas tutaj takie jak Interval, YearWeek, YearQuarter, i więcej .

Basil Bourque
źródło
3
Zastanawiam się, jak mogę uzyskać OP lub mody, aby oznaczyć twoją odpowiedź jako właściwą. Przyjęta odpowiedź jest tak nieaktualna.
sttaq
Bardzo ładnie, z wyjątkiem literówki. asStartOfDay () powinno mieć wartość atStartOfDay ().
Tullochgorum
@Tullochgorum Fixed. Dzięki. Do Twojej wiadomości, na Stack Overflow, możesz samodzielnie dokonywać takich zmian, jeśli masz na to ochotę.
Basil Bourque
5

Możesz też wykonać następujące czynności:

// untested
Calendar cal = GregorianCalendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, 23);// I might have the wrong Calendar constant...
cal.set(Calendar.MONTH, 8);// -1 as month is zero-based
cal.set(Calendar.YEAR, 2009);
Timestamp tstamp = new Timestamp(cal.getTimeInMillis());
Alex
źródło
2
ŹLE: wypróbuj System.out.println wyniku! Otrzymasz coś takiego: „2009-10-23 15: 26: 56.171” Miesiąc zaczyna się od 0, więc 9 to październik!
user85421
Wiedziałem, że jedna z tych stałych ma wartość zerową, dzięki. Zaktualizowano post.
Alex
1
Aha, i wstawiłem „niesprawdzone” :)
Alex
4

Zgodnie z API konstruktor, który zaakceptowałby rok, miesiąc itd., Jest przestarzały. Zamiast tego powinieneś użyć Konstruktora, który akceptuje długie. Możesz użyć implementacji Calendar, aby utworzyć żądaną datę i uzyskać dostęp do reprezentacji czasu jako długości, na przykład za pomocą metody getTimeInMillis .

Philipp
źródło
1

Dla kompletności również rozwiązanie z Joda-Time w wersji 2.5 i jego DateTimeklasie:

new Timestamp(new DateTime(2007, 9, 23, 0, 0, DateTimeZone.forID( "America/Montreal" )).getMillis())
user152468
źródło
1
Dobra odpowiedź, ale przegapiłeś jeden kluczowy element: strefę czasową . W przypadku pominięcia strefy czasowej do DateTimeobiektu zostanie zastosowana bieżąca domyślna strefa czasowa maszyny JVM . Oznacza to, że wyniki będą się różnić w zależności od różnych komputerów lub konfiguracji systemu operacyjnego hosta lub ustawień maszyny wirtualnej. Aby uzyskać przewidywalne wyniki, przekaż strefę czasową do tego DateTimekonstruktora. Wybierz odpowiednią nazwę strefy czasowej dla swojego zamiaru. Na przykład DateTimeZone.forID( "America/Montreal" )lub DateTimeZone.UTC.
Basil Bourque
Ten kod mógłby być krótszy. Nie ma potrzeby konwertowania do java.util.Date, aby uzyskać i przejść milisekundy-od- epoki . Po prostu zapytaj DateTimeobiekt o milisekundy-od-epoki. Wymień .toDate().getTime()się .getMillis().
Basil Bourque
@BasilBourque W zależności od okoliczności możesz chcieć pominąć strefę czasową, aby uzyskać przewidywalne wyniki. Wynik „W Twojej obecnej strefie czasowej” może być całkiem rozsądnym i przewidywalnym wynikiem. Po co kodować na stałe strefę czasową lub prosić użytkowników o ręczne ustawienie strefy czasowej, gdy ich komputer ma już ustawioną strefę czasową? Z pewnością byłbym bardzo zaskoczony, gdyby aplikacja na moim komputerze zaczęła generować daty dostosowane do strefy czasowej Ameryki / Montrealu.
dan carter
@dancarter Pominięcie opcjonalnej strefy czasowej prowadzi do nieporozumień. Pominięcie podnosi niejednoznaczność: (a) czy programista zamierzał polegać na domniemanej wartości domyślnej, czy (b) czy nie uwzględnił kwestii strefy czasowej (co jest zbyt częste). Jeśli rzeczywiście chcesz użyć bieżącej domyślnej strefy czasowej maszyny JVM, powiedz to wyraźnie , wywołując DateTimeZone.getDefault()i przekazując wynik jako opcjonalny argument. (Nawiasem mówiąc, to Locale.getDefault()samo dotyczy dwuznaczności opcjonalnych argumentów.)
Basil Bourque
-1

Bardziej ogólną odpowiedzią byłoby importowanie java.util.Date, a gdy chcesz ustawić timestampdatę równą bieżącej, po prostu ustaw ją na równą new Date().

CSquid
źródło
ponieważ ** Date ("string"); ** jest przestarzałe
Ashish Ratan,