-1

I have a question about converting from 12-hour am/pm format to 24-hour format. I have tried using SimpleDateFormat but encountered some problems.

enter image description here

As you can see, I printed 5 lines of original and converted time, but failed for cases ending with "PM". Note that some inputs are of the 24-hour format and others have the 12-hour am/pm format.

Below is the code I write for the conversion:

static String standardizeTime(String inputTime) throws ParseException {
        SimpleDateFormat[] testInputFormat = new SimpleDateFormat[2];

        SimpleDateFormat returnFormat = new SimpleDateFormat("HH:mm");
        testInputFormat[0] = new SimpleDateFormat("hh:mm aa");
        testInputFormat[1] = new SimpleDateFormat("HH:mm");
        
        testInputFormat[0].setLenient(false);
        testInputFormat[1].setLenient(false);

        Date time;
        for (int i = 0; i < testInputFormat.length; i++) {
            try {
                time = testInputFormat[i].parse(inputTime);
                return returnFormat.format(time);
            } catch (ParseException e) {
                continue;
            }
        }

        return "";
    }

What should I change to fix this problem?

  • I recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use `LocalTime` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Oct 25 '20 at 18:42

4 Answers4

2

This works as expected.

import java.text.SimpleDateFormat;

public class HelloWorld{

     public static void main(String []args) throws Exception {
         final SimpleDateFormat parser = new SimpleDateFormat("hh:mm aa");
         final SimpleDateFormat printer = new SimpleDateFormat("HH:mm");
        System.out.println(printer.format(parser.parse("4:07 pm")));
     }
}

Your code looks good so I think problem is elsewhere.

Alexander Pavlov
  • 2,264
  • 18
  • 25
  • 1
    Thank you for your answer, Alex. As you said, the problem is not here. It turns out that I need to include "Locale.ENGLISH" in the parser because the default language of my computer is not English. – JIKAI ZHANG Oct 24 '20 at 04:59
  • [Are “Your code works fine for me” answers acceptable?](https://meta.stackexchange.com/questions/118992/are-works-for-me-answers-valid) – Ole V.V. Oct 25 '20 at 19:04
1

I fixed my problem by referring to this post: java.text.ParseException: Unparseable date

The problem is, the default language of my computer is not English, so take Alexander's response as an example. I need to write:

import java.text.SimpleDateFormat;
import java.util.Locale;

public class HelloWorld{

     public static void main(String []args) throws Exception {
         final SimpleDateFormat parser = new SimpleDateFormat("hh:mm aa", Locale.ENGLISH);
         final SimpleDateFormat printer = new SimpleDateFormat("HH:mm");
         System.out.println(printer.format(parser.parse("4:07 pm")));
     }
}

Note the "Locale.ENGLISH" in parser!

0

Make sure to use Locale with date/time formatting API whenever the date/time contains letters because different locales have a different representation of letters.

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class Main {
    public static void main(String[] args) throws ParseException {
        DateFormat stfInput = new SimpleDateFormat("h:m a", Locale.ENGLISH);// 12-hour format
        DateFormat stfOutput = new SimpleDateFormat("HH:mm", Locale.ENGLISH);// 24-hour format
        Date time = stfInput.parse("02:57 AM");
        System.out.println(stfOutput.format(time));
        time = stfInput.parse("07:05 PM");
        System.out.println(stfOutput.format(time));
    }
}

Output:

02:57
19:05

Note: java.util date-time classes are outdated and error-prone and so is their formatting API, SimpleDateFormat. I suggest you should stop using them completely and switch to the modern date-time API. Learn more about the modern date-time API at Trail: Date Time.

If you are doing it for your 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.

Using the modern date-time API:

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("h:m a", Locale.ENGLISH);// 12-hour format
        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("HH:mm", Locale.ENGLISH);// 24-hour format
        LocalTime time = LocalTime.parse("02:57 AM", dtfInput);
        System.out.println(time.format(dtfOutput));
        time = LocalTime.parse("07:05 PM", dtfInput);
        System.out.println(time.format(dtfOutput));
    }
}

Output:

02:57
19:05
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
0

What should I change to fix this problem?

First and most importantly: I recommend that you use java.time, the modern Java date and time API, for your time work. The date-time classes that you tried to use, SimpleDateFormat and Date, are poorly designed and long outdated. The modern API is so much nicer to work with. The last half of the answer by Arvind Kumar Avinash shows you how. There is no reason for me to repeat it. And yes, Arvind’s code does fix your problem.

What went wrong in your code?

It’s been said that your problem is not providing an English-speaking locale to your formatter. This is part of the truth, but it doesn’t fully explain why 07:05 PM was converted to 07:05 where the correct conversion would have given 19:05.

What happened was that your first input formatter, the one with pattern hh:mm aa, failed at parsing because it used a language where PM would be called something else. Next the second formatter, with pattern HH:mm succeeded in parsing the string. Surprising, isn’t it? I consider it one of the many confusing traits of SimpleDateFormat that it doesn’t necessarily parse the entire string. It parsed the 07:05 part as hour of day and minute. Then it ignored the remainder of the string. In this way you got the result 07:05, which is incorrect, instead of the correct 19:05. This is just one of the reasons why you shouldn’t use SimpleDateFormat at all.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161