Search code examples
javadatetimestampdate-formattingdate-comparison

Translating from a String to a Timestamp and back


I work with the date in my API on Java. I want to get today's date and time, write it to a class and then to a csv file (I use a csv file as a data store). Then, to implement the function of getting a report on records for today, to get it and to compare it with today's date (exactly the date, without time). What is the best way to do this? Right now I'm storing this in Timestamp, but it doesn't seem to be correct and should I use String? Then I need two parsers? To translate from a string to a date and time and from that to just a DATE? Which library is better to use for this?

I wrote a translation from a string to a timestamp, is this correct?

default Timestamp StringToTimestamp(String date) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-YYYY");
    Date parsedDate = null;
    try {
        parsedDate = dateFormat.parse(date);
    } catch (ParseException e) {
        e.printStackTrace();
        log.error("Error in date parsing");
    }
    return new Timestamp(parsedDate.getTime());
}

UPD I changed my code for the java.time library, but it seems I did something wrong

 default LocalDate StringToTimestamp(String date) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern('yyyy-mm-dd');
        LocalDate date = LocalDate.parse(date, dtf);
        return date;
    }

UPD I edited the code according to the answer @OleV.V. It works really cool


Solution

  • java.time

    I recommend that you use java.time, the modern Java date and time API, for your date and time work. I suggest writing the current date and time with offset from UTC to the CSV file.

        OffsetDateTime dateTime = OffsetDateTime.now(ZoneId.systemDefault());
        String stringForCsvFile = dateTime.toString();
        System.out.println(stringForCsvFile);
    

    Output when running in my time zone just now:

    2020-12-26T11:02:07.368973+01:00

    The string is in ISO 8601 format, which should be the best to avoid surprises for anyone reading it. The classes of java.time generally print ISO 8601 format from their toString methods.

    Often you will value consistency higher than knowing which UTC offset was used when writing the file. If so, write the time in UTC to the file:

        Instant now = Instant.now();
        String stringForCsvFile = now.toString();
    

    2020-12-26T10:02:07.373439Z

    No matter which way you used above, after reading the timestamp from the file, convert like this:

        ZoneId zone = ZoneId.systemDefault();
        String stringFromCsvFile = "2020-12-26T11:02:07.368973+01:00";
        ZonedDateTime dateTime = OffsetDateTime.parse(stringFromCsvFile)
                .atZoneSameInstant(zone);
        LocalDate dateFromCsv = dateTime.toLocalDate();
        LocalDate today = LocalDate.now(zone);
        
        System.out.println("Same day? " + dateFromCsv.isEqual(today));
    

    Same day? true

    I have made sure that both dates I compare are in the time zone of the JVM where the program is running. Please consider whether there’s a specific time zone you want, and if so, set zone to something like ZoneId.of("Asia/Baku"). It matters: it is never the same date in all time zones.

    If you want to know whether the date is earlier or later, use the isBefore or isAfter method of LocalDate.

    Was your code correct?

    IMHO the worst problem with your code is using the old and poorly designed date-time classes: SimpleDateFormat, Date and Timestamp. SimpleDateFormat is a notorious troublemaker of a class. Date had severe design flaws in Java 1.0, therefore most constructors and methods were deprecated already in Java 1.1. Timestamp was never meant for other purposes than transferring high-precision timestamps to and from SQL databases (which we also don’t use it for anymore). And it’s a true hack on top of the already poorly designed Date class. I furthermore see nothing that you will want to use the high precision of Timestamp for, so using it here seems pointless.

    There is a bug in your code: You are using upper case YYYY in your format pattern. This is for week year and only useful with a week number. I tried giving 24-06-2021 to your method. It returned 2021-01-04 00:00:00.0. It’s 5 months 20 days off because of the mentioned error. Apparently SimpleDateFormat defaulted to the start of week 1 in the week year and ignored the month and day of month.

    As an aside, had you tried parsing with the same format pattern string with java.time, it would at least have told you that this was wrong.

    Links