Validate date & timestramp in java

kartik chougule :

I need to validate date in java the input date can be anything like

01-01-2019,2019-01-01,2019/01/01,2019/01/01,2017-02-14 19:30. 

I have the following code that can validate simple date without timestamp. I need to validate date with timestamp as well.In following code i have written a parseDate method which gives me format of date which we pass.

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

  public static void main(String[] args) {

        String date1 = parseDate("12-12-2019 10:10:10");
        boolean str1 = isValid(date1,"12-12-2019 10:10:10");
        System.out.println("str = " + str1);
  }

  private static final String[] formats = { 
  "yyyy-MM-dd'T'HH:mm:ss'Z'","yyyy-MM-dd'T'HH:mm:ssZ",
"yyyy-MM-dd'T'HH:mm:ss","yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
"yyyy-MM-dd'T'HH:mm:ss.SSSZ","yyyy-MM-dd HH:mm:ss", 
"MM/dd/yyyy HH:mm:ss","MM/dd/yyyy'T'HH:mm:ss.SSS'Z'", 
"MM/dd/yyyy'T'HH:mm:ss.SSSZ", "MM/dd/yyyy'T'HH:mm:ss.SSS", 
"MM/dd/yyyy'T'HH:mm:ssZ","MM/dd/yyyy'T'HH:mm:ss", 
"yyyy:MM:dd HH:mm:ss","yyyy-MM-dd HH:mm:ss.SSSSSS",
"yyyy/MM/dd HH:mm:ss","MM/dd/yyyy","dd/MM/yyyy",
"dd-MM-yyyy","yyyy/MM/dd"
   };

    public static String parseDate(String dateString) {
        int count = 0;

                    if (dateString != null) {
            for (String dateFormat : formats) {
                SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
                sdf.setLenient(false);

                try {
                    count ++;
                    sdf.parse(dateString);
                    System.out.println("sdf.parse(dateString);" + sdf.parse(dateString));
                    System.out.println("dateFormat  " + dateFormat);
                    System.out.println("count" + count);
                    return dateFormat;
                } catch (ParseException e) {
              }
            }
        }
        return "yyyy-MM-dd";
    }

  public static boolean isValid(String format,String inDate) {

    System.out.println("format  " + format);
    System.out.println("inDate  " + inDate);

    if (inDate == null || !inDate.matches("^([0-2][0-9]|(3)[0-1])(\\-)(((0)[0-9])|((1)[0-2]))(\\-)\\d{4}$")
    && !inDate.matches("^([0-2][0-9]|(3)[0-1])(\\/)(((0)[0-9])|((1)[0-2]))(\\/)\\d{4}$") 
    && !inDate.matches("([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))")
    && !inDate.matches("([12]\\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[12]\\d|3[01]))"))
    return false;
    SimpleDateFormat df = new SimpleDateFormat(format);
    try {
        df.parse(inDate);
        return true;
    } catch (ParseException ex) {
        return false;
    }


}
Basil Bourque :

Not possible to accommodate all formats

"MM/dd/yyyy","dd/MM/yyyy"

It is impossible to accurately parse such values.

Is 01/02/2020 the first of February or the second of January? No way to know.

Avoid legacy date-time classes

You are using the wrong classes. Never use Date, SimpleDateFormat, Calendar, and such. Use only java.time classes.

  • The Date class represents a moment, not a date nor a date-with-time. A moment is a date, a time-of-day, and an offset-from-UTC or time zone.
  • And that terrible class was supplanted years ago by java.time.Instant as of the adoption of JSR 310.

ISO 8601

By the way, the ISO 8601 standard defines practical formats for exchanging date-time values as text. The formats are easy to parse by machine, and easy to read by humans across cultures.

I suggest you educate the publisher of your data about these standard formats.

Tip: The modern java.time classes use these formats by default when parsing/generating strings. So no need to specify a formatting pattern.

LocalDate

The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.

DateTimeFormatter

Define a DateTimeFormatter for each of your expected formats.

Notice how I changed your example data to use 23 for day-of-month, to distinguish month versus day. If your actual inputs can be in either order, then your job is impossible. You should push this problem back to the people publishing such haphazard poorly-formatted data.

List< DateTimeFormatter > formatters = 
    List.of(
        DateTimeFormatter.ofPattern( "MM-dd-uuuu" ) ,  // 01-23-2019
        DateTimeFormatter.ISO_LOCAL_DATE ,             // 2019-01-23
        DateTimeFormatter.ofPattern( "uuuu/MM/dd" )    // 2019/01/23
    )
;

Loop that list to try each one, trapping for exception when a misfit.

LocalDate localDate = null ;
for( DateTimeFormatter f : formatters ) {
    try{
        localDate = LocalDate.parse( input , f ) ;
    } catch ( DateTimeParseException e ) {
        // Ignoring exception, as it is expected. 
    }
}
if( Objects.isNull( localDate ) ) { … deal with unexpected input }

LocalDateTime

And check length of input to detect the date-with-time inputs versus date-only inputs.

if( input.length() > 10 ) {  
    DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm" ) ;  // 2017-02-14 19:30
    LocalDateTime ldt = LocalDateTime.parse( input , f ) ;  // Add trap for `DateTimeParseException`. 
}

Example app

Here is an entire working example app.

/* package whatever; // don't place package name! */

import java.util.*;
import java.lang.*;
import java.io.*;

import java.time.* ;
import java.time.format.* ;
import java.time.temporal.* ;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {

List< DateTimeFormatter > formatters = 
    List.of(
        DateTimeFormatter.ofPattern( "MM-dd-uuuu" ) ,  // 01-23-2019
        DateTimeFormatter.ISO_LOCAL_DATE ,             // 2019-01-23
        DateTimeFormatter.ofPattern( "uuuu/MM/dd" )    // 2019/01/23
    )
;

List< String > inputs = 
    List.of(
        "01-23-2019" , 
        "2019-01-23" ,
        "2019/01/23" ,
        "banana"
    )
;

for( String input : inputs ) {
    LocalDate localDate = null ;
    for( DateTimeFormatter formatter : formatters ) 
    {
        try{
            localDate = LocalDate.parse( input , formatter ) ;
        } catch ( DateTimeParseException e ) {
            // Ignoring exception, as it is expected. 
        }
    }
    if( Objects.isNull( localDate ) ) 
    { // Deal with unexpected input 
        System.out.println( "ERROR: Unexpected input: " + input ) ;
    } else {
        System.out.println( "Input: " + input + " ➙ " + localDate.toString() ) ;
    }
}



    }
}

See it run live at IdeOne.com.

Input: 01-23-2019 ➙ 2019-01-23

Input: 2019-01-23 ➙ 2019-01-23

Input: 2019/01/23 ➙ 2019-01-23

ERROR: Unexpected input: banana

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=131761&siteId=1