1

I have a small gui which have a datepicker and a textbox where I enter a time (HH:mm).

I want to create a method whish takes the Date from the datepicker and adds the time (HH:mm) to the datepicker-date and then returns the Date so I can save it in a database.

I want to have the final date in this format "yyyy-MM-dd HH:mm"

This is what I have tried:

public Date getCalibrationDate(){
        String time = getTime();
        int hours = Integer.parseInt(time.substring(0,2));
        int minutes = Integer.parseInt(time.substring(2,4));
        Date date = java.sql.Date.valueOf(kalibreringsdatum.getValue());

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.set(Calendar.HOUR_OF_DAY, hours);
        calendar.set(Calendar.MINUTE,minutes);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String dateAsString = sdf.format(calendar.getTime());
        Date dateTime = null;

        try {
            dateTime = sdf.parse(dateAsString);
        } catch (ParseException e) {
            System.out.println("Could not parse date");
            e.printStackTrace();
        }
        return dateTime;
    }

But it returns the date in this way: Tue Dec 11 11:22:00 CET 2018. What am I doing wrong and how can I simplify the method?

Burton
  • 407
  • 1
  • 6
  • 19
  • 1
    Are you using java 8? – Ulad Dec 10 '18 at 21:11
  • Yes, sorry forgot to mention that. – Burton Dec 10 '18 at 21:12
  • 4
    Use the `java.time` API - much easier solution – MadProgrammer Dec 10 '18 at 21:13
  • 1
    Not sure why you would use `String dateAsString = sdf.format(calendar.getTime());` followed by `dateTime = sdf.parse(dateAsString);` is `Calendar#getTime` returns an instance of `java.util.Date` – MadProgrammer Dec 10 '18 at 21:14
  • 2
    Unless there's some very specific reason, avoid using `java.sql.Date`, prefer `java.util.Date` - better yet, use `java.time.LocalDateTime` – MadProgrammer Dec 10 '18 at 21:15
  • Why are you converting the `Date` to a formatted `String`, then back into a `Date` again? You're doing the formatting into the format you want, but then you're discarding it. – Krease Dec 10 '18 at 21:17
  • 1
    FYI, the terribly troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Dec 10 '18 at 22:20
  • Which type does `kalibreringsdatum.getValue()` return? `LocalDate`? `String`? Or something else? In any case a `Date` cannot have a format, so this is not possible: “I want to have the final date in this format "yyyy-MM-dd HH:mm"”. Fortunately it is also completely unnecessary, as [the answer by Basil Bourque](https://stackoverflow.com/a/53714934/5772882) shows. – Ole V.V. Dec 11 '18 at 09:00
  • I cannot reproduce your problem. Instead if `time` is `11:22`, I get `java.lang.NumberFormatException: For input string: ":2"`. – Ole V.V. Dec 11 '18 at 09:03

2 Answers2

3

tl;dr

For database column of type TIMESTAMP WITHOUT TIME ZONE.

myPreparedStatement                        // As of JDBC 4.2, send/receive java.time objects to/from your database.
.setObject(                                // Call `PreparedStatement::setObject` and `ResultSet::getObject` for java.time objects.
    … ,                                    // Fill-in to indicate which placeholder in SQL statement.
    LocalDateTime.of(                      // Represent a date with time-of-day, but lacking in zone/offset so NOT a moment, NOT a point on the timeline.
        LocalDate.parse( "2018-01-23" ) ,  // Parse the date-only value.
        LocalTime.parse( "21:54" )         // Parse the time-of-day.
    )                                      // Returns a `LocalDateTime` object.
)

For database column of type TIMESTAMP WITH TIME ZONE.

myPreparedStatement                        // As of JDBC 4.2, send/receive java.time objects to/from your database.
.setObject(                                // Call `PreparedStatement::setObject` and `ResultSet::getObject` for java.time objects.
    … ,                                    // Fill-in to indicate which placeholder in SQL statement.
    LocalDateTime.of(                      // Represent a date with time-of-day, but lacking in zone/offset so NOT a moment, NOT a point on the timeline.
        LocalDate.parse( "2018-01-23" ) ,  // Parse the date-only value.
        LocalTime.parse( "21:54" )         // Parse the time-of-day.
    )                                      // Returns a `LocalDateTime` object.
    .atZone(                               // Assign a time zone to make a moment.
        ZoneId.of( "Pacific/Auckland" )    // Real time zones have a proper name in `Continent/Region` format. Never use 2-4 letter pseudo-zones such as `PDT`, `IST`, `CST`, etc. 
    )                                      // Returns a `ZonedDateTime` object.
    .toOffsetDateTime()                    // Strip out the time zone, leaving only a mere offset-from-UTC (a number of hours-minutes-seconds). Returns a `OffsetDateTime` object.
    .withOffsetSameInstant(                // Adjust the offset-from-UTC to UTC itself (an offset of zero). Same moment, different wall-clock time.
        ZoneOffset.UTC 
    )                                      // Returns another `OffsetDateTime` object.
)

java.time

The modern approach uses the java.time classes that years ago supplanted the terrible old legacy classes (Calendar, Date, SimpleDateFormat, etc.).

LocalDate

The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.

The common SQL format for a date-only value in text is YYYY-MM-DD. This is also the format defined by the ISO 8601 standard. The java.time classes use the ISO 8601 formats by default when parsing/generating strings. So no need to specify a formatting pattern.

LocalDate ld = LocalDate.parse( "2018-01-23" ) ;

Similar for a string in format of HH:MM for hours and minutes of a time-of-day.

LocalTime lt = LocalTime.parse( "21:54" ) ;

Combine the date with the time.

LocalDateTime ldt = LocalDateTime.of( ld , lt ) ;

ldt.toString(): 2018-01-23T21:54

Be aware that a LocalDateTime, purposely lacking any concept of time zone or offset-from-UTC, is not a moment, is not a point on the timeline. As such, it is only appropriate to save to a database in a column of a data type akin to the SQL-standard TIMESTAMP WITHOUT TIME ZONE.

JDBC 4.2

As of JDBC 4.2, we can directly exchange java.time objects with the database via setObject & getObject.

myPreparedStatement.setObject( … , ldt ) ;

Retrieval.

LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;

ZonedDateTime

If you want to work with moments, actual points on the timeline, use the appropriate Java classes (Instant, OffsetDateTime, ZonedDateTime).

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;

OffsetDateTime

Now we have a moment at hand. Usually best to focus on UTC when moving dates around such as transferring to a database.

OffsetDateTime odtUtc = zdt.toOffsetDateTime().withOffset( ZoneOffset.UTC ) ;

Send to database.

myPreparedStatement.setObject( … , odtUtc ) ;

Retrieval.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
0

You can use SimpleDateFormat to get what you want:

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateAndTime {

public static void main(String[] args) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm");
    System.out.println(sdf.format(new Date()))
}
}
Sergei Voychuk
  • 171
  • 2
  • 8
  • FYI, the terribly troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Dec 10 '18 at 22:20
  • You can, but as others have said, you shouldn’t in 2018. And your code will not always give the expected result. – Ole V.V. Dec 11 '18 at 05:13
  • 1
    Basil Bourque, thank you, really useful information. Will keep it in mind. – Sergei Voychuk Dec 11 '18 at 21:43