Jak przekonwertować znacznik czasu na datę w Javie?

105

Jak przekonwertować „znacznik czasu” na datepo otrzymaniu licznika w Javie?

Mój obecny kod wygląda następująco:

public class GetCurrentDateTime {

    public int data() {
        int count = 0;
        java.sql.Timestamp timeStamp = new Timestamp(System.currentTimeMillis());
        java.sql.Date date = new java.sql.Date(timeStamp.getTime()); 
        System.out.println(date);
        //count++;

        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/pro", "root", "");

            PreparedStatement statement = con.prepareStatement("select * from orders where status='Q' AND date=CURDATE()");
            ResultSet result = statement.executeQuery();
            while (result.next()) {
                // Do something with the row returned.
                count++; //if the first col is a count.
            }
        } catch (Exception exc) {
            System.out.println(exc.getMessage());
        }

        return count;
    }
}

To jest moja baza danych: wprowadź opis obrazu tutaj

Tutaj otrzymałem wynik 2012-08-07 0, ale równoważne zapytanie zwraca 3. Dlaczego otrzymuję 0?

Krishna Veni
źródło
Czy możesz nam pokazać przykłady tego, jak wyglądają dane w tabeli?
oldrinb
data (1344255451,1344255537,1344312502) i status mają (Q, Q, Q)
Krishna Veni
Tytuł tego pytania to czerwony śledź . Prawdziwym problemem jest niewłaściwe użycie PreparedStatementz nieprawidłową składnią. Nie można osadzać zmiennych Java w tekście łańcucha SQL. Zamiast tego osadzaj ?w ciągu SQL, a następnie wywołaj setmetody, aby przekazać wartości do PreparedStatement. Zobacz poprawną odpowiedź Sujaya i odpowiedź przez tenorsax .
Basil Bourque

Odpowiedzi:

188

Po prostu utwórz nowy Dateobiekt z wartością stempla getTime()jako parametrem.

Oto przykład (używam przykładowego znacznika czasu bieżącego czasu):

Timestamp stamp = new Timestamp(System.currentTimeMillis());
Date date = new Date(stamp.getTime());
System.out.println(date);
Alex Coleman
źródło
@ vs06 Dlaczego uważasz, że jest przestarzały? Najnowsze dokumenty Java 7 i 8 mówią inaczej ( docs.oracle.com/javase/7/docs/api/java/util/Date.html#getTime () i docs.oracle.com/javase/8/docs/api /java/util/Date.html#getTime-- )
Alex Coleman
4
Spowoduje to powstanie niepoprawnego wyniku, jeśli strefa czasowa znacznika czasu i strefa czasowa maszyny JVM są różne.
Robert Mugattarov
Jak na przykład sformatować to do 14.03.2014?
shurrok
6
Nienawidzę, gdy ppl używają bibliotek w swoich odpowiedziach i oczekuję, że wszyscy będą wiedzieć, jak je zaimportować: /
Sodj
38
// timestamp to Date
long timestamp = 5607059900000; //Example -> in ms
Date d = new Date(timestamp );

// Date to timestamp
long timestamp = d.getTime();

//If you want the current timestamp :
Calendar c = Calendar.getInstance();
long timestamp = c.getTimeInMillis();
VincentLamoute
źródło
Dlaczego pomnożyłeś to przez 1000?
Sharpless512
3
Ponieważ inicjalizacja daty jest w milisekundach, a znacznik czasu w sekundach! To samo dotyczy wszystkich innych konwersji! To jest dobre ?
VincentLamoute
10

Właśnie:

Timestamp timestamp = new Timestamp(long);
Date date = new Date(timestamp.getTime());
Alberto Cerqueira
źródło
7

Szukałem tego od dłuższego czasu, okazuje się, że konwerter Eposh robi to łatwo:

long epoch = new java.text.SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse("01/01/1970 01:00:00").getTime() / 1000;

Lub odwrotnie:

String date = new java.text.SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(new java.util.Date (epoch*1000));
Joker 00
źródło
6

tl; dr

LocalDate.now( ZoneId.of( "Africa/Tunis" ) )
    .atStartOfDay( ZoneId.of( "Africa/Tunis" ) )
    .toEpochSecond()

LocalDate.now( ZoneId.of( "Africa/Tunis" ) )
    .plusDays( 1 )
    .atStartOfDay( ZoneId.of( "Africa/Tunis" ) )
    .toEpochSecond()

"SELECT * FROM orders WHERE placed >= ? AND placed < ? ; "

myPreparedStatement.setObject( 1 , start )
myPreparedStatement.setObject( 2 , stop )

java.time

Używasz kłopotliwych starych klas daty i czasu, które są teraz starsze, wyparte przez nowoczesne klasy java.time .

Najwyraźniej przechowujesz moment w swojej bazie danych w kolumnie pewnego typu całkowitego. To jest niefortunne. Zamiast tego powinieneś używać kolumny typu, takiego jak standard SQL TIMESTAMP WITH TIME ZONE. Ale w przypadku tej odpowiedzi będziemy pracować z tym, co mamy.

Jeśli Twoje rekordy przedstawiają momenty z rozdzielczością milisekund i chcesz, aby wszystkie rekordy obejmowały cały dzień, potrzebujemy przedziału czasu. Musimy mieć moment rozpoczęcia i moment zakończenia. Twoje zapytanie ma tylko jedno kryterium daty i czasu, w którym powinno mieć parę.

LocalDateKlasa reprezentuje wartość data-tylko bez time-of-day i bez strefy czasowej.

Strefa czasowa ma kluczowe znaczenie przy ustalaniu daty. W dowolnym momencie data różni się na całym świecie według strefy. Na przykład, kilka minut po północy w Paryżu Francja jest nowym dniem, podczas gdy w Montrealu Quebec wciąż trwa „wczoraj” .

Jeśli nie określono strefy czasowej, maszyna JVM niejawnie stosuje swoją bieżącą domyślną strefę czasową. To ustawienie domyślne może się zmienić w dowolnym momencie, więc wyniki mogą się różnić. Lepiej jest jawnie określić żądaną / oczekiwaną strefę czasową jako argument.

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 znormalizowane, a nawet nie unikalne (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

Jeśli chcesz użyć bieżącej domyślnej strefy czasowej maszyny JVM, poproś o to i podaj jako argument. W przypadku pominięcia bieżąca wartość domyślna maszyny JVM jest stosowana niejawnie. Lepiej, aby było to jawne, ponieważ wartość domyślna może zostać zmieniona w dowolnym momencie podczas działania przez dowolny kod w dowolnym wątku dowolnej aplikacji w JVM.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Lub podaj datę. Możesz ustawić miesiąc za pomocą liczby, z rozsądną numeracją 1-12 dla stycznia-grudnia.

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

Lub, lepiej, użyj Monthwstępnie zdefiniowanych obiektów wyliczeniowych, po jednym dla każdego miesiąca w roku. Porada: Użyj tych Monthobiektów w całej bazie kodu, a nie zwykłej liczby całkowitej, aby kod był bardziej samodokumentujący, zapewniał prawidłowe wartości i zapewniał bezpieczeństwo typów .

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

Mając LocalDatew ręku, musimy następnie przekształcić to w parę chwil, początek i koniec dnia. Nie zakładaj, że dzień zaczyna się o godzinie 00:00:00. Z powodu anomalii, takich jak czas letni (DST), dzień może rozpocząć się o innej godzinie, na przykład o godzinie 01:00:00. Niech java.time określi pierwszą porę dnia. Przekazujemy ZoneIdargument LocalDate::atStartOfDaydo wyszukania takich anomalii. Wynik to ZonedDateTime.

ZonedDateTime zdtStart = ld.atStartOfDay( z ) ;

Ogólnie najlepszym podejściem do definiowania przedziału czasu jest podejście Half-Open, w którym początek jest włączający, a koniec wyłączny . Tak więc dzień zaczyna się od swojej pierwszej chwili i kończy się, ale nie wliczając, pierwszej chwili następnego dnia.

ZonedDateTime zdtStop = ld.plusDays( 1 ).atStartOfDay( z ) ;  // Determine the following date, and ask for the first moment of that day.

Nasze zapytanie przez cały dzień nie może korzystać z polecenia SQL BETWEEN. To polecenie to Fully-Closed ( []) (zarówno początek, jak i koniec są włącznie), gdzie tak, jak chcemy, Half-Open ( [)). Używamy pary kryteriów >=i <.

Twoja kolumna ma złą nazwę. Unikaj tysiąca słów zarezerwowanych przez różne bazy danych. Użyjmy placedw tym przykładzie.

Twój kod powinien zawierać ?symbole zastępcze, w których można określić nasze momenty.

String sql = "SELECT * FROM orders WHERE placed >= ? AND placed < ? ; " ;

Ale mamy ZonedDateTimeobiekty w ręku, podczas gdy twoja baza danych najwyraźniej przechowuje liczby całkowite, jak omówiono powyżej. Jeśli nie zdefiniowano swoją kolumnę właściwie moglibyśmy po prostu przekazać ZonedDateTimeobiektów z dowolnego sterownika JDBC nośnej JDBC 4.2 lub nowszej.

Ale zamiast tego potrzebujemy odliczać od epoki w pełnych sekundach. Zakładam, że datą odniesienia dla twojej epoki jest pierwsza chwila roku 1970 UTC. Uważaj na możliwą utratę danych, ponieważ ZonedDateTimeklasa ma rozdzielczość nanosekundową. Każda ułamkowa część sekundy zostanie obcięta w następnych wierszach.

long start = zdtStart().toEpochSecond() ;  // Transform to a count of whole seconds since 1970-01-01T00:00:00Z.
long stop = zdtStop().toEpochSecond() ; 

Teraz jesteśmy gotowi do przekazania tych liczb całkowitych do naszego kodu SQL zdefiniowanego powyżej.

PreparedStatement ps = con.prepareStatement( sql );
ps.setObject( 1 , start ) ;
ps.setObject( 2 , stop ) ;
ResultSet rs = ps.executeQuery();

Gdy pobierasz wartości całkowite z ResultSet, możesz przekształcić je w Instantobiekty (zawsze w UTC) lub w ZonedDateTimeobiekty (z przypisaną strefą czasową).

Instant instant = rs.getObject(  , Instant.class ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

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 .

Skąd wziąć klasy java.time?

  • Java SE 8 , Java SE 9 i nowsze
    • Wbudowany.
    • Część standardowego interfejsu API języka Java z dołączoną implementacją.
    • Java 9 dodaje kilka drobnych funkcji i poprawek.
  • Java SE 6 i Java SE 7
    • Wiele funkcji java.time jest przenoszonych z powrotem do Java 6 i 7 w ThreeTen-Backport .
  • Android
    • Późniejsze wersje implementacji klas java.time w pakietach Androida.
    • Na wcześniejszym Androidzie ThreeTenABP projekt dostosowuje ThreeTen-backportu (wymienione powyżej). Zobacz Jak używać ThreeTenABP… .

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
4

Przede wszystkim nie wykorzystujesz zalet korzystania z domeny PreparedStatement. Najpierw zasugerowałbym zmodyfikowanie swojego PreparedStatementw następujący sposób:

PreparedStatement statement = con.prepareStatement("select * from orders where status=? AND date=?")

Następnie możesz użyć, statement.setXX(param_index, param_value)aby ustawić odpowiednie wartości. Aby dokonać konwersji na timestamp, spójrz na następujące javadocs:

PreparedStatement.setTimeStamp ()
Timestamp

Mam nadzieję że to pomoże!

Sujay
źródło
4

W Androidzie jest to bardzo proste. Po prostu użyj klasy Calender, aby uzyskać currentTimeMillis.

Timestamp stamp = new Timestamp(Calendar.getInstance().getTimeInMillis());
Date date = new Date(stamp.getTime());
Log.d("Current date Time is   "  +date.toString());

W Javie po prostu użyj System.currentTimeMillis (), aby uzyskać aktualny znacznik czasu

Ashish Saini
źródło
3

Nie jestem pewien, co próbujesz wybrać w zapytaniu, ale pamiętaj, że UNIX_TIMESTAMP()bez argumentów zwraca teraz czas. Prawdopodobnie powinieneś podać prawidłowy czas jako argument lub zmienić warunek.

EDYTOWAĆ:

Oto przykład zapytania związanego z czasem na podstawie pytania:

PreparedStatement statement = con
        .prepareStatement("select * from orders where status='Q' AND date > ?");
Date date = new SimpleDateFormat("dd/MM/yyyy").parse("01/01/2000");
statement.setDate(1, new java.sql.Date(date.getTime()));

EDYCJA: kolumna sygnatura czasowa

W przypadku użycia timestamp java.sql.Timestampi PreparedStatement.setTimestamp () , tj .:

PreparedStatement statement = con
        .prepareStatement("select * from orders where status='Q' AND date > ?");
Date date = new SimpleDateFormat("dd/MM/yyyy").parse("01/01/2000");
Timestamp timestamp = new Timestamp(date.getTime());
statement.setTimestamp(1, timestamp);
tenorsax
źródło
teraz mój warunek to wybierz * z xcart_orders, gdzie status = 'P' ORAZ data = CURDATE (). teraz wyświetlane również tylko zero
Krishna Veni
@krishnaveni jakie rekordy próbujesz wybrać?
tenorsax,
date (11111111,123456767,122333344) i status = (Q, Q, Q) .. wszystkie są zapisane w mojej bazie danych. teraz chcę sprawdzić zapytanie i uzyskać wartość licznika i wyświetlić na mojej konsoli (tj.) ile dane są dopasowywane po zwróceniu wartości zliczania
Krishna Veni
@krishnaveni Jeśli chcesz, aby zestaw wyników był związany określoną datą, użyj tej daty w zapytaniu, w przeciwnym razie usuń warunek daty.
tenorsax
w moim kodzie działa poprawnie, gdy data jest w formacie rrrr-mm-dd zapisanym w mojej bazie danych. Ale teraz moja data jest zapisana w sygnaturze czasowej w formacie 1343469690. Jak uzyskać wartość zliczania? Jak napisałem kod tutaj
Krishna Veni
3

new Date(timestamp.getTime())powinno działać, ale nowy, fantazyjny sposób w Javie 8 (który może być bardziej elegancki i bezpieczniejszy, a także pomóc w korzystaniu z nowych klas czasu) to wywołanie Date.from(timestamp.toInstant()).

(Nie polegaj na tym, że Timestampsam w sobie jest przykładem Date; zobacz wyjaśnienie w komentarzach do innej odpowiedzi ).

Garret Wilson
źródło
3
    Timestamp tsp = new Timestamp(System.currentTimeMillis());
   java.util.Date dateformat = new java.util.Date(tsp.getTime());
PAN I
źródło
3

Czuję się zobowiązany do odpowiedzi, ponieważ inne odpowiedzi wydają się być niezależne od strefy czasowej, na co aplikacja w świecie rzeczywistym nie może sobie pozwolić. Aby zapewnić poprawną konwersję datownika na datę, gdy znacznik czasu i maszyna JVM używają różnych stref czasowych, można użyć funkcji LocalDateTime firmy Joda Time (lub LocalDateTime w języku Java8) w następujący sposób:

Timestamp timestamp = resultSet.getTimestamp("time_column");
LocalDateTime localDateTime = new LocalDateTime(timestamp);
Date trueDate = localDateTime.toDate(DateTimeZone.UTC.toTimeZone());

Poniższy przykład zakłada, że ​​znacznik czasu to UTC (jak to zwykle ma miejsce w przypadku baz danych). Jeśli twoje znaczniki czasu znajdują się w innej strefie czasowej, zmień parametr strefy czasowej w toDateinstrukcji.

Robert Mugattarov
źródło
2

spróbuj użyć tego kodu java:

Timestamp stamp = new Timestamp(System.currentTimeMillis());
Date date = new Date(stamp.getTime());
DateFormat f = new SimpleDateFormat("yyyy-MM-dd");
DateFormat f1 = new SimpleDateFormat("yyyy/MM/dd");
String d = f.format(date);
String d1 = f1.format(date);
System.out.println(d);
System.out.println(d1);
Pomóż deweloperowi
źródło
0

Zakładając, że masz już istniejące java.util.Date date:

Timestamp timestamp = new Timestamp(long);
date.setTime( l_timestamp.getTime() );
Albizia
źródło
0

Możesz użyć tej metody, aby uzyskać datę z sygnatury czasowej i strefy czasowej określonego obszaru.

public String getDayOfTimestamp(long yourLinuxTimestamp, String timeZone) {
    Calendar cal = Calendar.getInstance();
    cal.setTimeInMillis(yourLinuxTimestamp * 1000);
    cal.setTimeZone(TimeZone.getTimeZone(timeZone));
    Date date = cal.getTime();
}
Manoj Patidar
źródło
-1
String timestamp="";
Date temp=null;
try {
    temp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(getDateCurrentTimeZone(Long.parseLong(timestamp)));
} catch (ParseException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
int dayMonth=temp.getDate();
int dayWeek=temp.getDay();
int hour=temp.getHours();
int minute=temp.getMinutes();
int month=temp.getMonth()+1;
int year=temp.getYear()+1900;
user1485365
źródło
-3
DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
Date fecha = getDateInTimestamp(); 
José Ángel Becerra Bernáldez
źródło