0

I've this code

LocalDateTime localDateTime = LocalDateTime.parse("1777-11-11T00:00:00.000");
System.out.println("DateTimeZone.getDefault default" + DateTimeZone.getDefault());
System.out.println("Milliseconds UTC" + localDateTime.toDateTime(DateTimeZone.UTC).getMillis());
System.out.println("Milliseconds Europe rome" + localDateTime.toDateTime(DateTimeZone.forID("Europe/Rome")).getMillis());
java.sql.Timestamp t = new java.sql.Timestamp(localDateTime.toDateTime(DateTimeZone.forID("Europe/Rome")).getMillis());
System.out.println("End Date: "+  new java.sql.Timestamp(localDateTime.toDateTime(DateTimeZone.forID("Europe/Rome")).getMillis()));
        

where i convert a date from org.joda.time.LocalDateTime to java.sql.date

The output is

DateTimeZone.getDefault defaultEurope/Rome
Milliseconds UTC   -6063292800000
Milliseconds Europe rome  -6063295796000
End Date: 1777-11-11 00:10:04.0

So minutes and seconds are wrong. Why this happen? How can i solve?

Thanks

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • I recommend you neither use `java.sql.Date` nor `java.sql.Timestamp`. Both classes are poorly designed and long outdated. Instead use for example `LocalDate` or `LocalDateTime` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). In addition java.time has replaced Joda-Time, so for simpler and modern code go all-in on java.time. Then you may not need any conversion at all. – Ole V.V. Mar 01 '21 at 05:50

1 Answers1

1

So minutes and seconds are wrong. Why this happen?

It happens because there was a zone offset of 49 minutes and 56 seconds until 1893-10-31T23:49 in Italy.

enter image description here

Check this page for more information.

Also, note the following fact about org.joda.time.LocalDateTime#toDateTime:

When the time zone is applied, the local date-time may be affected by daylight saving. In a daylight saving gap, when the local time does not exist, this method will throw an exception. In a daylight saving overlap, when the same local time occurs twice, this method returns the first occurrence of the local time.

The following code demonstrates:

  1. A LocalDateTime until 1893-10-31T23:49 will be converted to DateTime with an offset of 49 minutes and 56 seconds.
  2. A LocalDateTime from 1893-10-31T23:50 to 1893-10-31T23:59 will throw exception as mentioned above.
  3. A LocalDateTime starting with 1893-11-01T00:00 will be converted to DateTime with an offset of +01:00 hours.

Demo:

import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;

public class Main {
    public static void main(String[] args) {
        // Test date-time strings
        String[] arr = { "1893-10-31T23:49:00.000", "1893-11-01T00:00:00.000", "1893-10-31T23:50:00.000" };
        
        for (String dt : arr) {
            LocalDateTime localDateTime = LocalDateTime.parse(dt);
            System.out.println(localDateTime);
            System.out.println(localDateTime.toDateTime(DateTimeZone.forID("Europe/Rome")));
        }
    }
}

Output:

1893-10-31T23:49:00.000
1893-10-31T23:49:00.000+00:49:56
1893-11-01T00:00:00.000
1893-11-01T00:00:00.000+01:00
1893-10-31T23:50:00.000
Exception in thread "main" org.joda.time.IllegalInstantException: Illegal instant due to time zone offset transition (daylight savings time 'gap'): 1893-10-31T23:50:00.000 (Europe/Rome)
    at org.joda.time.chrono.ZonedChronology.localToUTC(ZonedChronology.java:157)
    at org.joda.time.chrono.ZonedChronology.getDateTimeMillis(ZonedChronology.java:122)
    at org.joda.time.chrono.AssembledChronology.getDateTimeMillis(AssembledChronology.java:133)
    at org.joda.time.base.BaseDateTime.<init>(BaseDateTime.java:257)
    at org.joda.time.DateTime.<init>(DateTime.java:532)
    at org.joda.time.LocalDateTime.toDateTime(LocalDateTime.java:753)
    at Main.main(Main.java:12)

It is recommended to switch from the Joda-Time to the modern date-time API.*

Check the following notice at the Home Page of Joda-Time:

Joda-Time is the de facto standard date and time library for Java prior to Java SE 8. Users are now asked to migrate to java.time (JSR-310).

Using java.time API:

import java.time.LocalDateTime;
import java.time.ZoneId;

public class Main {
    public static void main(String[] args) {
        // Test date-time strings
        String[] arr = { "1893-10-31T23:49:00.000", "1893-11-01T00:00:00.000", "1893-10-31T23:50:00.000" };
        ZoneId zoneId = ZoneId.of("Europe/Rome");

        for (String dt : arr) {
            LocalDateTime localDateTime = LocalDateTime.parse(dt);
            System.out.println(localDateTime);
            System.out.println(localDateTime.atZone(zoneId));
        }
    }
}

Output:

1893-10-31T23:49
1893-10-31T23:49+00:49:56[Europe/Rome]
1893-11-01T00:00
1893-11-01T00:00+01:00[Europe/Rome]
1893-10-31T23:50
1893-11-01T00:00:04+01:00[Europe/Rome]

Learn more about the java.time API from Trail: Date Time.


* 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.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110