2

I have the following code for parsing dates:

public Boolean isDate(String date, String dateFormat) {
        try {
            DateTimeFormat.forPattern(dateFormat).parseDateTime(date);

        } catch(Exception e) {
            return false;
        }

        return true;

    }

This works well with more recent dates like 20071001 with format yyyyMMdd. However for dates earlier than 1970, like 19600101 with the same format of yyyyMMdd, the method returns false.

Any ideas on how I can sort this out will be appreciated very much.

UPDATE:

The exception I get is:

Cannot parse "19400101": Illegal instant due to time zone offset transition (Africa/Nairobi)

And this is how I'm calling the method:

if(validationUtils.isDate(propVal, dateFormat) == false) {
                    String msg = "Not a valid DATE";
                    Quartet<String, String, String, String> t = new Quartet<String, String, String, String>(recNo, field, propVal, msg);
                    errors.add(t);
                }

The class containing the isDate method is a bean which I wire using @Autowired IValidationUtils validationUtils. This is not the only validation I'm doing. Other validation stuff succeeds, and this, among others has led me to the conclusion that the issue is with Joda Time.

UPDATE (SOLUTION):

Following @Ettiene's suggestion (in the answer below), I got a solution to my issue. Revised working code is:

public Boolean isDate(String date, String dateFormat) {
        try {
            DateTimeFormatter fmt = DateTimeFormat.forPattern(dateFormat);
            DateTime dt = fmt.withZone(DateTimeZone.UTC).parseDateTime(date);

        } catch(Exception e) {
            return false;
        }

        return true;

    }
okello
  • 601
  • 10
  • 27
  • 1
    that's because epoch starts at 1/1/1970 –  May 15 '13 at 12:16
  • Does that mean I can't use Joda Time to parse dates earlier than 1-jan-1970? – okello May 15 '13 at 12:18
  • 2
    @hob So negative numbers no longer exist? And we cannot use a program to register someone's date of birth if he is 40 years old? – SJuan76 May 15 '13 at 12:18
  • there may be a workaround i'll think about it you may have to use julian date rather than joda though –  May 15 '13 at 12:19
  • ofc joda can process dates in negative epoch timestamp.. It's something else wrong here – Gjordis May 15 '13 at 12:20
  • @hob, any pointer to where I can get started with Julian? – okello May 15 '13 at 12:20
  • 1
    It works absolutely fine for me with `DateTimeFormat.forPattern("yyyyMMdd").parseDateTime("19600101")`. Please produce a short but *complete* program demonstrating the problem. – Jon Skeet May 15 '13 at 12:21
  • see here http://stackoverflow.com/questions/3706937/dates-before-january-1st-1970 this might help ful for u – PSR May 15 '13 at 12:21
  • i meant gregorian sorry –  May 15 '13 at 12:21
  • you didn't post the stack trace – Bhavik Shah May 15 '13 at 12:23
  • @Jon, All I'm doing is just determining whether a given string is a valid date. The code above returns false for all dates earlier than 1970. Can you spot any problem with it? – okello May 15 '13 at 12:24
  • @okello: Well the snippet I provided works without any exception. Again, please provide a short but *complete* program demonstrating the failure. (It's also not clear why you're returning `Boolean` rather than `boolean`.) – Jon Skeet May 15 '13 at 12:33
  • @Jon, the code above is what is called. As to why I'm returning Boolean and not boolean, I prefer the object to the primitives; just a personal taste. I'm pasting the exception trace in a few minutes. – okello May 15 '13 at 12:39
  • @okello: Ah - now you've given us the exception information, it's very straightforward, as Etienne has described. Basically you should use UTC to avoid this. – Jon Skeet May 15 '13 at 13:04

2 Answers2

2

This issue seems to be related to transition from winter time to summer time. The problem is that some dates aren't valid in some timezones because of the transition.

For example, in France/Paris timezone, 2013-03-31T02:30 is invalid because the switch from winter time to summer time happened at 2:00am this day, hence the minute following 2013-03-31T01:59 is 2013-03-31T03:00.

I guess that in your timezone, okello, before 1970, the transition was happening January 1st at midnight. Thus, 1960-01-01T00:00 is invalid (but 1959-12-31T00:00 and 1960-01-02T00:00 are valid).

Remember that when the hour of day is unspecified, midnight is assumed.

Étienne Miret
  • 6,448
  • 5
  • 24
  • 36
  • 1
    It would be a good idea to specify the simplest way of avoiding this: set the time zone of the formatter to UTC. – Jon Skeet May 15 '13 at 13:04
1

Don't use parseDateTime(), use parseLocalDate() (available since 2.0)

This is the conceptually correct way (you are not parsing a datetime but a date) and is robust (you do not need to worry about timezones, DST transitions and all that stuff that is completely alien to your problem).

Furthermore, you should only catch IllegalArgumentException, other exceptions should be rethrown or catched differently.

leonbloy
  • 73,180
  • 20
  • 142
  • 190
  • this looks more elegant than the one above. I've tested it out and it works. All I'm parsing are dates that do not contain time information. So, I agree, as you've explained, that `parseDateTime` is not relevant to me. `parseLocalDate` is more spot on. +1. – okello May 17 '13 at 06:15