1

I extract DATE information from Oracle Database in two different ways: by query and by stored procedure. I read the value by

String day = rs.getString("DAY");

obtaining:

by query: 2017-01-01 00:00:00:0
by stored procedure: 01-JAN-17

I need to convert them in a unique format, that is

yyyy-MM-dd

I do not know in advance how the value will be extracted (query or stored), so I do not know in advance which is the format.

Is there a generic way to convert in the target format? I'm looking for a way to convert two different input strings in a common output format

In other words, I need a "black box" code that, given in input a unknown string, converts it in yyyy-MM-dd.

Thanks

Fab
  • 1,145
  • 7
  • 20
  • 40
  • Possible duplicate of [Java string to date conversion](https://stackoverflow.com/questions/4216745/java-string-to-date-conversion) – Saif Ahmad Dec 01 '17 at 09:48
  • I know how to convert string to date. I'm looking for a generic way to parse two dfferent input strings in a unique output format. – Fab Dec 01 '17 at 09:51
  • 1
    Better approach is to retrieve objects from database rather than mere strings: `LocalDate ld = myResultSet.getObject( "DAY" , LocalDate.class )` – Basil Bourque Dec 01 '17 at 17:16
  • 1
    @BasilBourque is absolutely right. Furthermore, you get your desired format, `yyyy-MM-dd`, from `LocalDate.toString()` (provided that the date is in the common era), it could hardly be easier. – Ole V.V. Dec 02 '17 at 08:46

5 Answers5

2

You may want to use SimpleDateFormat with formats like:

f0 = new SimpleDateFormat( "yyyy-MM-dd" ),
f1 = new SimpleDateFormat( "dd-MMM-yy" ),
f2 = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss:0" );

I have not taken care of time zones, you may want to think about that, too, unless the database contains only data from one time zone.

Then you can

switch( day.length() ) {
  case 10: return f0.parse( day );
  case 21: return f1.parse( day );
  default: throw Exception( "..." ); // invalid format
}

Of course, better define appropriate format constants so that the meaning of 10 and 21 is better documented.

  • 1
    Please don’t teach the young ones to use the long outdated classes `SimpleDateFormat` and friends. Today we have so much better in [`java.time`, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Dec 02 '17 at 08:43
  • 1
    This Answer uses troublesome old date-time classes that are now legacy, supplanted years ago by the java.time classes. – Basil Bourque Dec 02 '17 at 16:24
  • Thanks, you are probably right that one day all classes will be deprecated. So I should add that this solution should work for Java 1.2 to 8. – Bernhard Bodenstorfer May 25 '18 at 06:31
0

You can test the lengh of the returned string and then use the SimpleDateFormat class to convert the date to your pattern.

example from a project of mine :

DataM1 dataM1 = new DataM1();

        System.out.println("===>Ticket n°"+(k+1));

        SimpleDateFormat sdf = new SimpleDateFormat(fr.alteca.outilindicateurs.statics.Date.FORMAT_DATE_REDMINE);
        SimpleDateFormat sdf2 = new SimpleDateFormat(fr.alteca.outilindicateurs.statics.Date.FORMAT_DATE_OUTIL);

        String strDateCorrectionPrevue = (String) datesCorrectionPrevue.get(k);
        String strDateResolution = (String) datesResolution.get(k);

        System.out.println("===> date de correction prévue "+strDateCorrectionPrevue);
        System.out.println("===> date de resolution "+strDateResolution);


        Date dateCorrectionPrevue = sdf.parse(strDateCorrectionPrevue);
        Date dateResolution = sdf.parse(strDateResolution);

        long a = dateResolution.getTime();
        long b = dateCorrectionPrevue.getTime();

        double c = b-a;


        Param.nf.setMaximumFractionDigits(2);
        Param.nf.setMinimumFractionDigits(2);
        Param.nf.setRoundingMode(RoundingMode.HALF_UP);
        String fn = Param.nf.format(c/Param.MILLISECONDS_PER_DAY);

        double d = Param.nf.parse(fn).doubleValue();


        dataM1.setId(k);
        if (d>=-1) {
            dataM1.setDelaisTenu(true);
        }
        dataM1.setPerformance(d);
        dataM1.setDateCorrectionPrevue(sdf2.format(dateCorrectionPrevue));
        dataM1.setDateResolution(sdf2.format(dateResolution));
        listeDataM1.add(dataM1);
Philippe Merle
  • 115
  • 2
  • 4
  • 13
0

You can use one function with try/catch:

public static String convertDate(String date)
   {

      SimpleDateFormat dateFormatQuery = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
      SimpleDateFormat dateFormatStored = new SimpleDateFormat("dd-MMM-yy");
      SimpleDateFormat dateFormatRet = new SimpleDateFormat("yyyy-MM-dd");
      Date ret = null;

      try
      {
         ret = dateFormatQuery.parse(date);
      }
      catch (ParseException e)
      {
         try
         {
            ret = dateFormatStored.parse(date);
         }
         catch (ParseException e1)
         {
            e.printStackTrace();
         }
      }

      return dateFormatRet.format(ret);
   }
KL_
  • 1,503
  • 1
  • 8
  • 13
  • 1
    Throwing and catching exceptions is very slow so a solution that prevents exceptions from occurring is much better. – Eelke Dec 01 '17 at 10:36
  • 1
    sorry but using try/catch block as flow control is not considered good/best practice. – arthur Dec 01 '17 at 10:57
  • 1
    Please don’t teach the young ones to use the long outdated classes `SimpleDateFormat` and friends. Today we have so much better in [`java.time`, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Dec 02 '17 at 08:43
  • 1
    This Answer uses troublesome old date-time classes that are now legacy, supplanted years ago by the java.time classes. – Basil Bourque Dec 02 '17 at 16:24
0

Just use simpledate format patterns for parsing dates- doc, examples can be found on the same page

For month in short format, please notice, pattern is MMM

example:

        String date1 = "2017-01-01 00:00:00:0";
        String date2 = "01-JAN-17";


        final String datePattern1 = "YYYY-dd-MM HH:mm:ss:S";
        final String datePattern2 = "dd-MMM-yy";

        SimpleDateFormat sdf1 = new SimpleDateFormat(datePattern1);
        SimpleDateFormat sdf2 = new SimpleDateFormat(datePattern2);

        try {
            System.out.println("date1: "  + sdf1.parse(date1));
            System.out.println("date2: " + sdf2.parse(date2));
        } catch (Exception e) {
            e.printStackTrace();
        }

output

date1: Sun Jan 01 00:00:00 CET 2017
date2: Sun Jan 01 00:00:00 CET 2017

btw SimpleDateFormat.parse can throw unparsable exception

xxxvodnikxxx
  • 1,270
  • 2
  • 18
  • 37
  • 2
    This Answer uses troublesome old date-time classes that are now legacy, supplanted years ago by the java.time classes. – Basil Bourque Dec 02 '17 at 16:25
0

You can use an approach of attempting matching either of the String formats coming for the db;

where there is a match then converts Date String --- to ----> Date Object. Then converts Date Object -- to --> Date String in new Format.

for that you need for each string matching attempt:

  • A Pattern instance
  • A Regex for the date input from the db
  • a date format string to be used in parsing the date string to the date object

at then just converts the date Object to your wanted String format.

in code, it looks like this

// stuff for the first format out of the db
String dateInput_1 = "2017-01-01 00:00:00:0";
String dateInput_1_Regex = "\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}:\\d{1}";
String dateInputFormat_1 = "yyyy-MM-dd HH:mm:ss:S";
Pattern pattern_1 = Pattern.compile(dateInput_1_Regex);

// stuff for the second format out of the db
String dateInput_2 = "01-JAN-17";
String dateInput_2_Regex = "\\d{2}-[A-Z]{3}-\\d{2}";
String dateInputFormat_2 = "dd-MMM-yy";
Pattern pattern_2 = Pattern.compile(dateInput_2_Regex);

// Dateformat and Date for converting/parsing between Date and Date-String
SimpleDateFormat sdf;
Date tempDate = null;

// if there is a match for the first date format string out the db,
if (pattern_1.matcher(dateInput_1).matches()) {
    sdf = new SimpleDateFormat(dateInputFormat_1);
    // store in a neutral date;
    tempDate = sdf.parse(dateInput_1);
}

// if there is a match for the second date format string out the db,
else if (pattern_2.matcher(dateInput_2).matches()) {
    sdf = new SimpleDateFormat(dateInputFormat_2);
    // store in a neutral date;
    tempDate = sdf.parse(dateInput_2);
}

// no matter which match was done, convert it to your expected Date String
String newDateString = new SimpleDateFormat("yyyy-MM-dd").format(tempDate);
System.out.println("new Date: " + newDateString);
  • Matching first with a Pattern objet will help control the flow of your code, and allow to use SimpleDateFormat only for your parsing/formatting job, thus avoiding to use exception to control the flow.
  • variables were named to make undertstanding easier.
arthur
  • 3,245
  • 4
  • 25
  • 34