最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - org.apache.commons.lang3.time.DateUtils is not parsing the dates for March 9th 2025 2am UTC time - Stack Overflow

programmeradmin4浏览0评论

I saw some strange behavior in my production application; .apachemons.lang3.time.DateUtils is throwing a java.text.ParseException. So I thought it was some code issue, but it turned out it's only having issues with March 9th, 2025, 2am time stamps. So I tried running some tests and found DateUtils.parseDateWithLeniency is unable to parse the date but DateUtils.parseDate is working. All the dates are working before and after that one hour. Not sure if it's a bug in the Java Calendar. I observed areAllFieldsSet in the false state in the Calendar class. Does anyone has any insight into this?

Test code tried locally

import java.text.ParseException;
import java.util.Date;

import .apachemons.lang3.time.DateUtils;

public class Test11 {

    public static void main(String[] args) {
        String dateString = "2025-03-09T02:37:51.742";
        
        try {
            Date date = DateUtils.parseDateStrictly(dateString,new String[]{
            "yyyy-MM-dd'T'HH:mm:ss.SSS"});
            System.out.println(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

}

Unable to parse the date: 2025-03-09T02:37:51.742
    at .apachemons.lang3.time.DateUtils.parseDateWithLeniency(DateUtils.java:391)
    at .apachemons.lang3.time.DateUtils.parseDateStrictly(DateUtils.java:333)
    at .apachemons.lang3.time.DateUtils.parseDateStrictly(DateUtils.java:311)
    at com.test.Test11.main(Test11.java:17)

A few failed dates for reference:

2025-03-09T02:52:51.261
2025-03-09T02:45:25.032
2025-03-09T02:08:01.013
2025-03-09T02:59:06.913
2025-03-09T02:57:20.466
2025-03-09T02:19:46.928
2025-03-09T02:45:19.957
2025-03-09T02:49:34.463
2025-03-09T02:13:09.896
2025-03-09T02:04:15.99
2025-03-09T02:09:53.982
2025-03-09T02:10:24.47
2025-03-09T02:24:27.696
2025-03-09T02:17:03.064
2025-03-09T02:05:58.489
2025-03-09T02:24:05.871
2025-03-09T02:41:06.302
2025-03-09T02:04:24.478
2025-03-09T02:32:36.959
2025-03-09T02:26:20.384
2025-03-09T02:40:51.959
2025-03-09T02:33:41.93
2025-03-09T02:58:00.669
2025-03-09T02:48:26.187

I tried running the sample strings and observed the issue for a one hour period.

I saw some strange behavior in my production application; .apachemons.lang3.time.DateUtils is throwing a java.text.ParseException. So I thought it was some code issue, but it turned out it's only having issues with March 9th, 2025, 2am time stamps. So I tried running some tests and found DateUtils.parseDateWithLeniency is unable to parse the date but DateUtils.parseDate is working. All the dates are working before and after that one hour. Not sure if it's a bug in the Java Calendar. I observed areAllFieldsSet in the false state in the Calendar class. Does anyone has any insight into this?

Test code tried locally

import java.text.ParseException;
import java.util.Date;

import .apachemons.lang3.time.DateUtils;

public class Test11 {

    public static void main(String[] args) {
        String dateString = "2025-03-09T02:37:51.742";
        
        try {
            Date date = DateUtils.parseDateStrictly(dateString,new String[]{
            "yyyy-MM-dd'T'HH:mm:ss.SSS"});
            System.out.println(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

}

Unable to parse the date: 2025-03-09T02:37:51.742
    at .apachemons.lang3.time.DateUtils.parseDateWithLeniency(DateUtils.java:391)
    at .apachemons.lang3.time.DateUtils.parseDateStrictly(DateUtils.java:333)
    at .apachemons.lang3.time.DateUtils.parseDateStrictly(DateUtils.java:311)
    at com.test.Test11.main(Test11.java:17)

A few failed dates for reference:

2025-03-09T02:52:51.261
2025-03-09T02:45:25.032
2025-03-09T02:08:01.013
2025-03-09T02:59:06.913
2025-03-09T02:57:20.466
2025-03-09T02:19:46.928
2025-03-09T02:45:19.957
2025-03-09T02:49:34.463
2025-03-09T02:13:09.896
2025-03-09T02:04:15.99
2025-03-09T02:09:53.982
2025-03-09T02:10:24.47
2025-03-09T02:24:27.696
2025-03-09T02:17:03.064
2025-03-09T02:05:58.489
2025-03-09T02:24:05.871
2025-03-09T02:41:06.302
2025-03-09T02:04:24.478
2025-03-09T02:32:36.959
2025-03-09T02:26:20.384
2025-03-09T02:40:51.959
2025-03-09T02:33:41.93
2025-03-09T02:58:00.669
2025-03-09T02:48:26.187

I tried running the sample strings and observed the issue for a one hour period.

Share Improve this question edited Mar 18 at 18:40 President James K. Polk 42.1k29 gold badges109 silver badges145 bronze badges asked Mar 17 at 20:32 vv1vv1 231 silver badge2 bronze badges 4
  • 4 Note that this is the day and time that Daylight Saving Time started in the US, on March 9th at 2:00am the clock was moved forward to 3:00am. So any time between 2:00 and 3:00 does not exist on that day, which probably means it cannot be parsed. – Marijn Commented Mar 17 at 20:41
  • Still using java.util.Date? Don’t! Use java.time, the modern Java date and time API. It seems that the class that you need is LocalDateTime. With LocalDateTime your parsing will work also for the mentioned date-times. – Anonymous Commented Mar 17 at 20:56
  • What do your date-time strings denote? Is there an assumed time zone in which to interpret them. Also asking because without know a time zone 2025-03-09T02:37:51.742 may denote a range of points in time that is 24 hours wide or wider. Also, what do you need to use the parsed date-times for? The good solution depends on that. – Anonymous Commented Mar 17 at 20:58
  • 1 Yes it's the timezone issue. The application is running on jdk11 and server is set to EST time zone. The payload received from vendor is UTC time zone. – vv1 Commented Mar 17 at 21:22
Add a comment  | 

2 Answers 2

Reset to default 4

java.time

I warmly recommend that you use java.time, the modern Java date and time API, for all of your date and time work.

    String dateString = "2025-03-09T02:37:51.742";
    LocalDateTime ldt = LocalDateTime.parse(dateString);
    System.out.println(ldt);

Output from this snippet is:

2025-03-09T02:37:51.742

A LocalDateTime is a date and time without time zone or offset from UTC. So it doesn’t know summer time (DST) and happily parses times that happen to fall in the spring gap that happens in your own default time zone between 2 and 3 in the night on this particular date where the clocks are turned forward.

Don’t we need a formatter? No, not in this case. Your string is in the standard ISO 8601 format. Which is good. The classes of java.time generally default parse the most common ISO 8601 variants natively, that is, without any explicit formatter. So parsing proceeds nicely without one. You also notice in the output that LocalDateTime prints the same format back from its toString method, just like the other java.time types do.

OffsetDateTime

In a comment you informed us:

The application is running on jdk11 and server is set to EST time zone. The payload received from vendor is UTC time zone.

When you know the date and time are in UTC, it’s advantageous (on the border of required) to use OffsetDateTime:

    OffsetDateTime odt = ldt.atOffset(ZoneOffset.UTC);
    System.out.println(odt);

2025-03-09T02:37:51.742Z

The trailing Z in the output is pronounced “Zulu” and denotes UTC. Now the date-time object also itself knows that it is in UTC, so you don’t need to keep track of it with the risks of error that that would have entailed.

An OffsetDateTime is date and time with an offset from UTC — in this case offset 0.

Don’t use Date and the other legacy date-time types

The Date class was always poorly designed and has fortunately been outdated since java.time was launched with Java 8 more than 10 years ago. Avoid it.

Only, if you need a Date for a legacy API that you cannot afford to upgrade to java.time just now, convert the OffsetDateTime from above:

    Date oldfashionedDate = Date.from(odt.toInstant());
    System.out.println(oldfashionedDate);

I ran this snippet in America/Toronto time zone, assuming that by “EST” you meant something in this direction. EST is ambiguous as many three letter abbreviations are, and it’s not a time zone since most of the people using North American Eastern Standard Time (EST) use Eastern Daylight Time (EDT) for the greater part of the year. In any case, in America/Toronto the output is:

Sat Mar 08 21:37:51 EST 2025

Since Eastern Standard Time is 5 hours behind UTC, this agrees with 02:37:51 on March 9th UTC from the string.

Tutorial link

Oracle Tutorial: Trail: Date Time explaining how to use java.time.

tl;dr

java.time.LocalDateTime               // Represents a date with time-of-day but no zone or offset. 
.parse ( "2025-03-09T02:37:51.742" )  // Parsing standard ISO 8601 format. Returns a `LocalDateTime` object. 
.atOffset ( ZoneOffset.UTC )          // Applies an offset from UTC of zero hours-minutes-seconds. Returns a `OffsetDateTime` object. 

java.time

You’re using terribly flawed date-time classes that are now legacy, supplanted by the modern java.time classes built into Java 8 and later.

LocalDateTime

Your string input represents a date with time of day, but lacks the context of a time zone or offset from UTC. So, parse as a LocalDateTime.

LocalDateTime ldt = LocalDateTime.parse ( "2025-03-09T02:37:51.742" ) ;

Be aware that this object does not represent a moment, is not a point on the timeline. Without a zone or offset, we have no way of knowing if this is 2 AM in Tokyo Japan, 2 AM in Toulouse France, or 2 AM in Toledo Ohio US — three different moments several hours apart.

ZonedDateTime

If you are certain your input was meant to represent a moment as seen in a particular time zone, specify that zone to generate a ZonedDateTime.

ZoneId z = ZoneId.of ( "America/New_York" ) ;
ZonedDateTime zdt = ldt.atZone ( z ) ;

Run this code at Ideone.

2025-03-09T03:37:51.742-04:00[America/New_York]

OffsetDateTime

Perhaps your input represents a moment “in UTC”, meaning an offset from UTC of zero hours-minutes-seconds. The constant ZoneOffset.UTC holds an offset of zero.

For offsets rather than time zone, use OffsetDateTime class rather than ZonedDateTime class. (A time zone is a named history of the past, present, and future changes to the offset used by people of a particular region as determined by their politicians.)

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;

DST at

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论