23

Does anyone know a good date parser for different languages/locales. The built-in parser of Java (SimpleDateFormat) is very strict. It should complete missing parts with the current date.

For example

  • if I do not enter the year (only day and month) then the current year should be used.
  • if the year is 08 then it should not parse 0008 because the current year pattern has 4 digits.

Edit: I want to parse the input from a user. For example if the locale date format of the user is "dd.mm.yyyy" and the user type only "12.11." then the parser should accept this as a valid date with the value "12.11.2008". The target is a good usability.

Horcrux7
  • 23,758
  • 21
  • 98
  • 156
  • 1
    "It should complete missing parts with the current date." And it *should* give me a Bentley. I'm not sure "should" is appropriate here. Can you rephrase this to say what you want, not what someone else should do? – S.Lott Oct 21 '08 at 16:09
  • FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque May 23 '18 at 23:34

11 Answers11

23

Check Joda Time, and its Freaky Formatters.

Java 8 includes JSR-310 so that could be a solution as well.

JodaStephen
  • 60,927
  • 15
  • 95
  • 117
Petteri H
  • 11,779
  • 12
  • 64
  • 94
  • I love Joda Time. It's so good, it'll be the basis of a rewrite of Date Time handling in Java 7 – Vinko Vrsalovic Oct 21 '08 at 15:20
  • 4
    So, how would the code to answer this question would look like using Joda Time? – Eduardo Aug 25 '10 at 16:15
  • FYI, the [*Joda-Time*](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the [*java.time*](http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque May 23 '18 at 23:23
14

From 43642, although not necessarily a duplicate:

See Apache Commons' DateUtils. There's a parseDate method that takes your String and multiple patterns to try and spits out a Date instance.

Community
  • 1
  • 1
Joe Liversedge
  • 4,124
  • 26
  • 19
8

(Edited for clarity.)

Personally, I think strict is good. So many different situations call for different rules around relaxed parsing, it's impossible to really put that into a common library comprehensively.

However, I would thoroughly recommend Joda Time instead of the built-in date/time classes in general. Their formatters and parsers are thread-safe and immutable, which helps too. Joda Time has some support for relaxed parsing, as shown in the other answer, but you should expect to have to provide some of the rules yourself.

JodaStephen
  • 60,927
  • 15
  • 95
  • 117
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
3

I would say JChronic if you're looking for something that will parse dates from natural "fuzzy" human input.

I've used both JChronic and Chronic (the original Ruby version) with great success.

matt
  • 78,533
  • 8
  • 163
  • 197
madlep
  • 47,370
  • 7
  • 42
  • 53
3

tl;dr

java.time.format.DateTimeFormatterBuilder::parseDefaulting

java.time

The DateTimeFormatter class parses strings into date-time objects.

You can create customized instances of DateTimeFormatter by using the DateTimeFormatterBuilder class. That builder class enables you to specify default values for missing components of the input string.

DateTimeFormatter f =
        new DateTimeFormatterBuilder()
                .appendPattern( "MM-dd" )
                .parseDefaulting(
                        ChronoField.YEAR ,
                        ZonedDateTime.now( ZoneId.of( "America/Montreal" ) ).getYear()
                )
                .toFormatter() ;

String input = "01-23" ;
LocalDate ld = LocalDate.parse( input , f ) ;

System.out.println( ld ) ;

ld.toString(): 2018-01-23

See also DateTimeFormatterBuilder with specified parseDefaulting conflicts for YEAR field.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
2

The POJava project on SourceForge has a DateTime object that parses dates from multiple languages (when month is specified as a name) and is configurable between MM-DD-YYYY and DD-MM-YYYY. It parses dates heuristically, picking out the most likely year, month, date, hour, minute, second, and time zone rather than supporting predefined formats. The jar file is about 60K in size.

There is ambiguity in interpretation of a date like "10-08" in that it could be intended as shorthand for either "2008-10-08" or "Oct 2008". You could append the year yourself if you are accepting the sort of shorthand you give in your example.

Proj: POJava Docs: HOWTO use DateTime

2

Your first requirement has been answered by Basil Bourque.

  • if I do not enter the year (only day and month) then the current year should be used.
  • if the year is 08 then it should not parse 0008 because the current year pattern has 4 digits.

DateTimeFormatter allows us to specify the optional patterns inside square brackets. For the second requirement, you can specify the optional pattern, [.[uuuu][uu]] while building the DateTimeFormatter.

Demo:

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Locale;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        // Replace JVM's ZoneId, ZoneId.systemDefault() with the applicable one e.g.
        // ZoneId.of("Europe/Berlin")
        int defaultYear = LocalDate.now(ZoneId.systemDefault()).getYear();

        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                                .appendPattern("dd.MM[.[uuuu][uu]]")
                                .parseDefaulting(ChronoField.YEAR, defaultYear)
                                .toFormatter(Locale.ENGLISH);
        
        // Test
        Stream.of(
                    "12.11",
                    "12.11.21",
                    "12.11.2021"
        ).forEach(s -> System.out.println(LocalDate.parse(s, dtf)));        
    }
}

Output:

2021-11-12
2021-11-12
2021-11-12

ONLINE DEMO

Learn more about the modern Date-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
1

I tried to implement an extensible PHP's strtotime in Java in this answer

Community
  • 1
  • 1
dfa
  • 114,442
  • 31
  • 189
  • 228
1

Use DateFormat ... Current standard until the welcome respite of Joda.

Ichorus
  • 4,567
  • 6
  • 38
  • 46
1

Calendar is usually the way to go, but understand that most Java Date management will be handled on your part if you want it done properly. Timezone is a good thing to look into if you have to manage international/cross-zone info. Joda Time is also a neat thing and is the inspiration behind the new suggested Date/Time concepts to be added to Java in JSR 310.

Hope this is helpful.

JodaStephen
  • 60,927
  • 15
  • 95
  • 117
codeLes
  • 3,021
  • 3
  • 29
  • 27
0

I would have to say +1 for JodaTime. In addition to parsing, Joda makes just about every date-related operation better.

Joey Gibson
  • 7,104
  • 1
  • 20
  • 14