Question

I m writing a program which involves converting java.util.Date to java.sql.Date...

I've done it using getTime() method...

           java.util.Date dt = new java.util.Date();
           java.text.DateFormat df = new java.text.SimpleDateFormat("dd/MM/yyyy");
           dt=df.parse("06/12/0785");
           java.sql.Date sqldate = new java.sql.Date(dt.getTime());
           System.out.print("\n\n\n "+dt.getTime()+"    "+sqldate);

I m getting a negative value for dt.getTime() and the value is correct for sqldate...

The doubt i've is

           `Is it safe to use negative seconds as epoch or is it vulnerable to bugs while implementing it in database in any way.....???

AND

It's printing wrong date for sqldate on setting date as 00/00/0000 instead of the one mentioned in the example....what might be the cause......and does there lie a solution.......???

Was it helpful?

Solution

If you parse a "00" as month, it will be regarded as December. The day "00" is the last day of the previous month, so the combinations is parsed as the 30th of November. As for the zero year, see Year 0000 in java. Negative values for .getTime() are no problem at all.

OTHER TIPS

Well, in epoch time, "0" would be the equivalent to January 1, 1970. Any date earlier than that would come out negative when you try to parse it.

Try changing the date string you are parsing to any date after 1970 and you will get a proper value.

Documentation says negative values are valid for java.sql.Date's constructor and setTime method:

http://docs.oracle.com/javase/6/docs/api/java/sql/Date.html#setTime(long)

I expect that using "00/00/0000" as a date is a problem as there is no zero month, day, or year.

http://en.wikipedia.org/wiki/0_(year)

The legacy date-time API (java.util date-time types and their formatting type, SimpleDateFormat etc.) is outdated and error-prone. Let's first understand how SimpleDateFormat erroneously processes a string like 00/00/0000 and later we will cover how the modern date-time API prevents an attempt to processes an invalid string like this.

The following demo will help us understand easily both, the concept and the problem:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;

public class Main {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdfInput = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
        SimpleDateFormat sdfOutput = new SimpleDateFormat("dd MMMM yG", Locale.ENGLISH);
        System.out.println(sdfOutput.format(sdfInput.parse("00/00/2021")));
    }
}

Output:

30 November 2020AD

Some facts about SimpleDateFormat:

  • SimpleDateFormat processes the month, 1 as January.
  • It processes the year, month and day-of-month in a circular fashion which is very similar to how int, and long are processed.

enter image description here

For the sake of completeness, look at the output of the following statements:

System.out.println(Integer.MAX_VALUE + 1); // -2147483648
System.out.println(Integer.MIN_VALUE - 1); // 2147483647

Based on this concept, this is how SimpleDateFormat has parsed 00/00/2021:

  • Month, 00: Go back to the last month i.e. December which also means the year will become 2020.
  • Day-of-month, 00: Go back to the last day of the last month which also means December will shift back one place to become November and the last day of November is 30.

Thus, the output will be 30 November 2020AD.

Quiz: What will be the output for the input string, -01/-01/2021?

If your answer is: 30 October 2020AD, you have understood it correctly.

Given below are some more examples:

SimpleDateFormat sdfInput = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
SimpleDateFormat sdfOutput = new SimpleDateFormat("dd MMMM yG", Locale.ENGLISH);
System.out.println(sdfOutput.format(sdfInput.parse("00/00/0000"))); // 30 November 2BC
System.out.println(sdfOutput.format(sdfInput.parse("00/-01/2021"))); // 31 October 2020AD
System.out.println(sdfOutput.format(sdfInput.parse("00/13/2021"))); // 31 December 2021AD
System.out.println(sdfOutput.format(sdfInput.parse("00/14/2021"))); // 31 January 2022AD

Why 2BC?

Luckily1. there is no year-0. Before 1AD, we have 1BC. So, we know year-0 as 1BC. If you go one year back, it will be 2BC. You would like to check this answer for some more explanation.

You will encounter many such surprises while using the legacy date-time API. For these reasons, it is recommended to stop using it completely and switch to java.time, the modern date-time API*.

java.time

Let's see how java.time, the modern API prevents an attempt to processes an invalid string like this:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        LocalDate.parse("00/00/0000", DateTimeFormatter.ofPattern("dd/MM/uuuu", Locale.ENGLISH));
    }
}

Output:

Exception in thread "main" java.time.format.DateTimeParseException: Text '00/00/0000' could not be parsed: Invalid value for MonthOfYear (valid values 1 - 12): 0

Learn more about java.time, the modern date-time API2. from Trail: Date Time.


1. Otherwise, it would have opened a can of worms regarding whether year-0 should be called 0AD or 0BC.

2. For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top