Jak przekonwertować java.util.Date na java.sql.Date?

453

Próbuję użyć java.util.Datejako danych wejściowych, a następnie utworzyć z nim zapytanie - więc potrzebuję java.sql.Date.

Byłem zaskoczony, gdy przekonałem się, że nie można przeprowadzić konwersji w sposób pośredni lub jawny - ale nawet nie wiem, jak to zrobić, ponieważ Java API jest dla mnie całkiem nowy.

David Ackerman
źródło
Podobny problem można znaleźć tutaj stackoverflow.com/questions/12131068/...
Lem,
Dla mnie okazało się, że nie musiałem konwertować. W import java.sql.*moim kodzie był błąd, zastępujący plik java.util.date i powodujący problemy przy przypisywaniu wartości daty, które były w porządku z tym ostatnim, ale nie pierwszym. HTH
HumanInDisguise
1
@DavidAckerman Czy rozumiesz, że java.util.Date to data i pora dnia, ale java.sql.Date to tylko data bez pory dnia? (W rzeczywistości istnieje pora dnia, ale jest to ignorowane, zły hack projektu klasy) W SQL DATEoznacza tylko datę.
Basil Bourque,
2
Rzeczywiście nie wiedziałem o niuansach w 2009 roku, a ponieważ to pytanie jest tak popularne, zmieniłem przyjętą odpowiedź na bardziej nowoczesną i kompletną. Dziękujemy wszystkim za wkład!
David Ackerman,

Odpowiedzi:

89

tl; dr

Jak przekonwertować java.util.Date na java.sql.Date?

Nie rób Obie klasy są przestarzałe.

  • Używaj klas java.time zamiast starszego typu java.util.Datei java.sql.DateJDBC 4.2 lub nowszego.
  • Konwertuj na / z java.time, jeśli współpracujesz z kodem, który nie został jeszcze zaktualizowany do java.time.

Przykładowe zapytanie z PreparedStatement.

myPreparedStatement.setObject( 
     ,                                         // Specify the ordinal number of which argument in SQL statement.
    myJavaUtilDate.toInstant()                  // Convert from legacy class `java.util.Date` (a moment in UTC) to a modern `java.time.Instant` (a moment in UTC).
        .atZone( ZoneId.of( "Africa/Tunis" ) )  // Adjust from UTC to a particular time zone, to determine a date. Instantiating a `ZonedDateTime`.
        .toLocalDate()                          // Extract a date-only `java.time.LocalDate` object from the date-time `ZonedDateTime` object.
)

Części zamienne:

  • Instantzamiast java.util.Date
    Oba stanowią moment w UTC. ale teraz z nanosekundami zamiast milisekund.
  • LocalDatezamiast java.sql.Date
    Oba reprezentują tylko datę, bez pory dnia i strefy czasowej.

Detale

Jeśli próbujesz pracować z wartościami opartymi tylko na dacie (bez pory dnia, strefy czasowej), użyj LocalDateklasy zamiast java.util.Date.

Tabela typów daty i godziny w Javie (zarówno starszej, jak i nowoczesnej) oraz w standardzie SQL.

java.time

W Javie 8 i nowszych kłopotliwe stare klasy daty i czasu dołączone do wczesnych wersji Javy zostały zastąpione przez nowy pakiet java.time . Zobacz samouczek Oracle . Duża część funkcji została przeniesiona z powrotem do Java 6 i 7 w ThreeTen-Backport, a następnie dostosowana do Androida w ThreeTenABP .

SQL typ danych DATE ma być data-tylko, ze nie ma czasu na dzień i bez strefy czasowej. Java nigdy nie miała takiej klasy † aż do wersji java.time.LocalDateJava 8. Stwórzmy taką wartość, uzyskując dzisiejszą datę według określonej strefy czasowej (strefa czasowa jest ważna przy ustalaniu daty, kiedy nowy dzień zaczyna się wcześniej w Paryżu niż w Montrealu, ponieważ przykład).

LocalDate todayLocalDate = LocalDate.now( ZoneId.of( "America/Montreal" ) );  // Use proper "continent/region" time zone names; never use 3-4 letter codes like "EST" or "IST".

W tym momencie możemy być skończeni. Jeśli Twój sterownik JDBC jest zgodny ze specyfikacją JDBC 4.2 , powinieneś być w stanie przejść LocalDateprzezsetObject w PreparedStatementcelu zapisania w polu „DATA SQL”.

myPreparedStatement.setObject( 1 , localDate );

Podobnie, użyj, ResultSet::getObjectaby pobrać z kolumny DATA SQL do JavyLocalDate obiektu . Określenie klasy w drugim argumencie powoduje, że kod jest bezpieczny dla typu .

LocalDate localDate = ResultSet.getObject( 1 , LocalDate.class );

Innymi słowy, całe to pytanie nie ma znaczenia w JDBC 4.2 lub nowszym.

Jeśli sterownik JDBC nie działa w ten sposób, musisz wrócić do konwersji na typy java.sql.

Konwertuj na java.sql.Date

Aby przekonwertować, użyj nowych metod dodanych do starych klas daty i godziny. Możemy zadzwonić, java.sql.Date.valueOf(…)aby przekonwertować LocalDate.

java.sql.Date sqlDate = java.sql.Date.valueOf( todayLocalDate );

I iść w innym kierunku.

LocalDate localDate = sqlDate.toLocalDate();

Konwertowanie z java.util.Date

Chociaż powinieneś unikać używania starych klas daty i godziny, możesz być do tego zmuszony podczas pracy z istniejącym kodem. Jeśli tak, możesz przekonwertować na / z java.time.

Przejdź przez Instantklasę, która reprezentuje chwilę na osi czasu w UTC. InstantJest podobny pomysłu do java.util.Date. Pamiętaj jednak, że Instantma rozdzielczość do nanosekund, a rozdzielczość java.util.Datetylko milisekund .

Aby przekonwertować, użyj nowych metod dodanych do starych klas. Na przykład java.util.Date.from( Instant )i java.util.Date::toInstant.

Instant instant = myUtilDate.toInstant();

Aby ustalić datę, potrzebujemy kontekstu strefy czasowej. W danym momencie data zmienia się na całym świecie w zależności od strefy czasowej. Zastosuj a, ZoneIdaby uzyskać ZonedDateTime.

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
LocalDate localDate = zdt.toLocalDate();

† Klasa java.sql.Date udaje, że jest tylko datą, bez pory dnia, ale w rzeczywistości robi porę dnia, dostosowaną do północy. Zagmatwane? Tak, stare lekcje daty i godziny są bałaganem.


O java.time

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

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

Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj stos przepełnienia dla wielu 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 potrzeba ciągów, nie ma potrzeby java.sql.*klas.

Gdzie można uzyskać klasy java.time?

Tabela, z której biblioteki java.time należy korzystać, w której wersji Java lub Android

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
478

Nieważne....

public class MainClass {

  public static void main(String[] args) {
    java.util.Date utilDate = new java.util.Date();
    java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
    System.out.println("utilDate:" + utilDate);
    System.out.println("sqlDate:" + sqlDate);

  }

}

wyjaśnia to. Link to http://www.java2s.com/Tutorial/Java/0040__Data-Type/ConvertfromajavautilDateObjecttoajavasqlDateObject.htm

David Ackerman
źródło
34
To nie jest wyraźna konwersja! Z Javadoc: „Jeśli podana wartość milisekund zawiera informacje o czasie, sterownik ustawi składniki czasu na czas w domyślnej strefie czasowej (strefie czasowej wirtualnej maszyny Java z uruchomioną aplikacją), która odpowiada zerowej GMT.” Więc bez względu na czas w java.util.Date, zostanie wstawiony jako 00:00:00 w kolumnie z typem danych ustawionym na DATE.
1
@David Ackerman ..... ta metoda zwraca epochsecondsie milisekund po 1,JAN,1970. Ale co, jeśli chcemy zapisać datę osoby przed tą datą .... lub coś w stylu0000-00-00 as default
Arjun KP
31
W moim przypadku poprawną odpowiedzią jest <code> java.sql.Timestamp sqlTimestamp = new java.sql.Timestamp (utilDate.getTime ()); </code>, ponieważ zachowuje pola czasu.
Alberto de Paola,
2
@ wired00 Tak, stare klasy daty i czasu w pakiecie z wczesnymi wersjami Javy są bałaganem , źle zaprojektowanym, w tym prymitywnymi hackami. O ile to możliwe, spróbuj użyć nowej struktury java.time w Javie 8 i nowszych. Te nowe klasy zastępują stare. Klasy java.time i stare klasy mają kilka wygodnych metod konwertowania tam i z powrotem - przydatne, gdy czekamy na aktualizację sterowników JDBC w celu bezpośredniego wykorzystania nowych typów java.time.
Basil Bourque,
1
@ wired00 Zobacz moją nową odpowiedź na to pytanie, aby dowiedzieć się, jak korzystać z java.time. Przeszukaj także StackOverflow, aby znaleźć wiele innych przykładów.
Basil Bourque,
39

Z drugą odpowiedzią możesz mieć problemy z informacją o czasie (porównaj daty z nieoczekiwanymi wynikami!)

Sugeruję:

java.util.Calendar cal = Calendar.getInstance();
java.util.Date utilDate = new java.util.Date(); // your util date
cal.setTime(utilDate);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);    
java.sql.Date sqlDate = new java.sql.Date(cal.getTime().getTime()); // your sql date
System.out.println("utilDate:" + utilDate);
System.out.println("sqlDate:" + sqlDate);
mauretto
źródło
5
Jeśli używa bazy danych java.sql.Date dla kolumny Data w bazie danych, ta informacja o czasie zostanie obcięta. Moim zdaniem przerobiłeś rozwiązanie.
darioo
4
Tak, może to zrobiłem. Czasami muszę porównać dane java.sql.Data z bieżącą datą i imho to najlepszy sposób. Mam nadzieję, że to może pomóc.
mauretto
Do Twojej wiadomości, strasznie kłopotliwe stare klasy daty i czasu, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą teraz spuścizną , wyparte przez klasy java.time wbudowane w Javę 8 i nowsze wersje . Zobacz samouczek Oracle .
Basil Bourque
Oczywiście ten temat był około 10 lat temu, przed java 8.
mauretto
26

Ta funkcja zwróci skonwertowaną datę SQL z obiektu daty java.

public java.sql.Date convertJavaDateToSqlDate(java.util.Date date) {
    return new java.sql.Date(date.getTime());
}
chetan
źródło
18

Konwersja java.util.Datana java.sql.Datastraci godzinę, minutę i sekundę. Więc jeśli jest to możliwe, sugeruję użyć java.sql.Timestamptego w następujący sposób:

prepareStatement.setTimestamp(1, new Timestamp(utilDate.getTime()));

Aby uzyskać więcej informacji, możesz sprawdzić to pytanie .

shellbye
źródło
16

W moim przypadku wybranie daty z JXDatePicker (kalendarz java) i zapisanie jej w bazie danych jako typ daty SQL, poniżej działa dobrze.

java.sql.Date date = new java.sql.Date(pickedDate.getDate().getTime());

gdzie pickedDate jest obiektem JXDatePicker

Jack Jay
źródło
5

Ta funkcja zwróci skonwertowaną datę SQL z obiektu daty java.

public static java.sql.Date convertFromJAVADateToSQLDate(
            java.util.Date javaDate) {
        java.sql.Date sqlDate = null;
        if (javaDate != null) {
            sqlDate = new Date(javaDate.getTime());
        }
        return sqlDate;
    }
Tanmay Kumar Shaw
źródło
3

Najpierw sformatuj plik java.util.Date. Następnie użyj sformatowanej daty, aby uzyskać datę w java.sql.Date

java.util.Date utilDate = "Your date"
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
final String stringDate= dateFormat.format(utilDate);
final java.sql.Date sqlDate=  java.sql.Date.valueOf(stringDate);
hackfield
źródło
2

Tutaj przykład konwersji daty Util na datę Sql i ten jest jednym z przykładów, których używam w moim projekcie, może ci również pomóc.

java.util.Date utilStartDate = table_Login.getDob();(orwhat ever date your give form obj)
java.sql.Date sqlStartDate = new java.sql.Date(utilStartDate.getTime());(converting date)
Kishan Bheemajiyani
źródło
2

Jestem nowicjuszem: po długim bieganiu działało. Myśl może być przydatna

     String bufDt =  bDOB.getText();  //data from form
     DateFormat dF = new SimpleDateFormat("dd-MM-yyyy"); //data in form is in this format
     Date bbdt = (Date)dF.parse(bufDt);  // string data is converted into java util date
     DateFormat dsF = new SimpleDateFormat("yyyy-MM-dd"); //converted date is reformatted for conversion to sql.date
     String ndt = dsF.format(bbdt); // java util date is converted to compatible java sql date
     java.sql.Date sqlDate=  java.sql.Date.valueOf(ndt);  // finally data from the form is convered to java sql. date for placing in database
PKSawmy
źródło
Do Twojej wiadomości, strasznie kłopotliwe stare klasy daty i czasu, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą teraz spuścizną , wyparte przez klasy java.time wbudowane w Javę 8 i nowsze wersje . Zobacz samouczek Oracle .
Basil Bourque
2
java.sql.Date sqlDate = new java.sql.Date(javaDate.getTime());

Tutaj javaDate jest instancją java.util.Date

Rajeev Ranjan
źródło
1
Naprawdę nie wydaje się dodawać niczego nowego w porównaniu do odpowiedzi Davida Ackermana, Chetana i Tanmay Kumar Shaw, prawda?
Ole VV,
1

Metoda porównywania 2 dat (data.data lub data_sql)

 public static boolean isSameDay(Date a, Date b) {
    Calendar calA = new GregorianCalendar();
    calA.setTime(a);

    Calendar calB = new GregorianCalendar();
    calB.setTime(b);

    final int yearA = calA.get(Calendar.YEAR);
    final int monthA = calA.get(Calendar.MONTH);
    final int dayA = calA.get(Calendar.DAY_OF_YEAR);

    final int yearB = calB.get(Calendar.YEAR);
    final int monthB = calB.get(Calendar.MONTH);
    final int dayB = calB.get(Calendar.DAY_OF_YEAR);

    return yearA == yearB && monthA == monthB && dayA == dayB;
}
Donovan Thomson
źródło
0

spróbuj tego

public static String toMysqlDateStr(Date date) {
    String dateForMySql = "";
    if (date == null) {
        dateForMySql = null;
    } else {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dateForMySql = sdf.format(date);
    }

    return dateForMySql;
}
kapil das
źródło
-1

Myślę, że najlepszym sposobem na konwersję jest:

static java.sql.Timestamp SQLDateTime(Long utilDate) {
    return new java.sql.Timestamp(utilDate);
}

Date date = new Date();
java.sql.Timestamp dt = SQLDateTime(date.getTime());

Jeśli chcesz wstawić dtzmienną do tabeli SQL, możesz:

insert into table (expireAt) values ('"+dt+"');
użytkownik6043502
źródło
1
Wydaje się, że jest to zasadniczo to samo, co odpowiedź zamieszczona rok wcześniej.
Bernhard Barker,
-3

używam następującego kodu, proszę wypróbować

DateFormat fm= new SimpleDateFormatter();

określ format daty, którą chcesz na przykład, "DD-MM_YYYY"lub 'YYYY-mm-dd' następnie użyj typu danych Data Java jako

fm.format("object of java.util.date");

wtedy przeanalizuje twoją datę

UmeshA
źródło
-3

Możesz użyć tej metody do konwersji daty użycia na datę sql,

DateUtilities.convertUtilDateToSql(java.util.Date)
Emmanuel Angelo.R
źródło
W standardowej bibliotece Java nie ma klasy DateUtilities (a nawet nie mogę znaleźć tej metody nigdzie po szybkim wyszukiwaniu w Google). Jeśli pochodzi z konkretnej biblioteki, możesz powiedzieć tyle i dołączyć link do dokumentów.
Bernhard Barker,
-4

Próbowałem następującego kodowania, które działało dobrze.

java.util.Date utilDate = nowa java.util.Date ();
java.sql.Date sqlDate = nowa java.sql.Date (utilDate);

PONRAJ
źródło
-8

Jeśli korzystasz z Myysql, kolumna daty może zostać przekazana jako ciąg znaków reprezentujący tę datę

więc używam klasy DateFormatter do sformatowania go, a następnie ustawiam go jako ciąg w instrukcji sql lub instrukcji przygotowanej

oto ilustracja kodu:

private String converUtilDateToSqlDate(java.util.Date utilDate) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    String sqlDate = sdf.format(utilDate);
    return sqlDate;
}

String date = converUtilDateToSqlDate (otherTransaction.getTransDate ());

// następnie podaj tę datę w instrukcji sql

Benjamin Ndugga
źródło
14
Witaj w Stackoverflow, mam kilka komentarzy do twojej odpowiedzi. Pytanie brzmiało: „jak przekonwertować plik java.util.Date na java.sql.Date”. Wklejony kod formatuje java.util.Date jako rrrr-MM-dd. W tym kontekście ma to ograniczone zastosowanie, ponieważ należy przekazać java.sql.Date bezpośrednio do sterowników jdbc zamiast robić to jako ciąg znaków.
jontro