0
votes

I am trying to create a method which converts DAY, MONTH, YEAR to Date object in Java

I have

String DAY = "31"
String YEAR = "2012"
String MONTH = "11"

I need a configurable Format as output.

String format = "MM/dd/yyy";

I will always get DAY string from "01" to "31" only
I will always get YEAR string from "1000" to "9999" only
I will always get MONTH string from "01" to "12" only (Never get Jan, Feb etc)

I understand that SimpleDateFormat(format) can work up to some extend.

new SimpleDateFormat("MM/dd/yyyy") will parse "02/01/2010" as Feb 01 2010 but
new SimpleDateFormat("mm/dd/yyyy") will parse "02/01/2010" as Jan 01 2010

Is it possible to write a generic method in java which converts given Strings (DAY, MONTH, YEAR) to Date object based on a configurable pattern?? and which can throw exception is I supply a wrong combination of DAY, MONTH, YEAR (like DAY = "31", MONTH = "02", YEAR = "2010")

Something like :

Date dateParser(String format){
  
  String DAY = "01";
  String YEAR = "1922";
  String MONTH = "02";
  
  
  return date;
}
2
SimpleDateFormat will do what you need. mm/dd/yyyy doesn't work because lowercase mm is for minutes not months.GriffeyDog
@GriffeyDog - Please do not suggest anyone use the outdated API. You will find hundreds of questions regarding the undesirable results people get by using java.util date-time API and SimpleDateFormat.Arvind Kumar Avinash
I recommend you neither use Date nor SimpleDateFormat. Those classes are poorly designed and long outdated, the latter in particular notoriously troublesome. Instead use LocalDate and DateTimeFormatter, both from java.time, the modern Java date and time API.Ole V.V.
Just FYI: Do not use Date anymore. It's outdated, having several problems and not anymore recommended to be used. Use, instead, LocalDateTime API (which also includes ZonedDateTime, LocalDate and LocalTime).Giorgi Tsiklauri
@ArvindKumarAvinash I'm not suggesting that the OP should use the outdated Date API, just answering the question as presented, where it appears the OP is using that API.GriffeyDog

2 Answers

2
votes

There are basically two ways:

  1. Parse each string to a number and put the numbers together to a date.
  2. Put the strings together to one string and parse it into a date.

Some middle forms are thinkable, but I recommend you take a pure stance and use one of the ways only. The answer by Arvind Kumar Avinash shows option 1. My taste is rather for option 2., so let me demonstrate.

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

    String format = "MM/dd/yyy";
    
    String day = "31";
    String year = "2012";
    String month = "11";
    
    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(format, Locale.US);
    
    String isoDateString = year + '-' + month + '-' + day;
    LocalDate date = LocalDate.parse(isoDateString);
    
    String formattedDate = date.format(dateFormatter);
    System.out.println(formattedDate);

Since there are only 30 days in November (month 11), this code very sensibly throws an exception:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2012-11-31' could not be parsed: Invalid date 'NOVEMBER 31'

That is, we have got input validation for free. For a valid date the code will parse the date and format as requested.

Link

Oracle tutorial: Date Time explaining how to use java.time.

1
votes

I recommend you switch from the outdated and error-prone java.util date-time API and SimpleDateFormat to the modern java.time date-time API and the corresponding formatting API (package, java.time.format). Learn more about the modern date-time API from Trail: Date Time.

Note that mm is used for minute; not for month. For month, you use MM. Check this for more information.

Using the modern date-time API:

import java.time.LocalDate;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(getLocalDate("2010", "02", "28"));
        System.out.println(getLocalDate("2010", "02", "31"));
    }

    static LocalDate getLocalDate(String year, String month, String dayOfMonth) {
        return LocalDate.of(Integer.parseInt(year), Integer.parseInt(month), Integer.parseInt(dayOfMonth));
    }
}

Output:

2010-02-28
Exception in thread "main" java.time.DateTimeException: Invalid date 'FEBRUARY 31'
    at java.base/java.time.LocalDate.create(LocalDate.java:459)
    at java.base/java.time.LocalDate.of(LocalDate.java:271)
    at Main.getLocalDate(Main.java:11)
    at Main.main(Main.java:7)

Note that a date-time object is supposed to store the information about date, time, time-zone etc. but not about the formatting. When you print an object of a date-time type, its is supposed to print what its toString method returns. If you need to print the date-time in a different format, you need a formatting class (e.g. DateTimeFormatter) which can return you a string in your desired pattern e.g.

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(getFormattedLocalDate("2010/02/28", "yyyy/MM/dd", "EEEE dd MMMM yyyy"));
        System.out.println(getFormattedLocalDate("28/02/2010", "dd/MM/yyyy", "yyyy MMM EEE dd"));
    }

    static String getFormattedLocalDate(String date, String inputPattern, String outputPattern) {
        return LocalDate.parse(date, DateTimeFormatter.ofPattern(inputPattern))
                .format(DateTimeFormatter.ofPattern(outputPattern));
    }
}

Output:

Sunday 28 February 2010
2010 Feb Sun 28