Java SimpleDateFormat 将“04:50 PM”转换为“16:50”

Java SimpleDateFormat convert "04:50 PM" to "16:50"

我有一个关于从 12 小时 am/pm 格式转换为 24 小时格式的问题。我试过使用 SimpleDateFormat 但遇到了一些问题。

如您所见,我打印了 5 行原始时间和转换后的时间,但对于以“PM”结尾的情况却失败了。请注意,有些输入是 24 小时制,而其他输入是 12 小时制 am/pm 格式。

下面是我为转换编写的代码:

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 "";
    }

我应该更改什么来解决这个问题?

这按预期工作。

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")));
     }
}

您的代码看起来不错,所以我认为问题出在其他地方。

我参考这个post解决了我的问题:java.text.ParseException: Unparseable date

问题是,我的电脑默认语言不是英文,所以以Alexander的回复为例。我需要写:

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")));
     }
}

注意解析器中的“Locale.ENGLISH”!

只要 date/time 包含字母,请务必使用 Locale 和 date/time 格式 API,因为不同的语言环境对字母的表示不同。

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));
    }
}

输出:

02:57
19:05

注: java.util date-time 类 已过时,error-prone 格式也已过时 API , SimpleDateFormat.我建议你应该完全停止使用它们并切换到 modern date-time API. Learn more about the modern date-time API at Trail: Date Time.

如果您正在为您的 Android 项目执行此操作,并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring and .

使用现代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));
    }
}

输出:

02:57
19:05

What should I change to fix this problem?

首先也是最重要的一点:我建议您使用 java.time,现代 Java 日期和时间 API,作为您的时间工作。您尝试使用的 date-time 类 SimpleDateFormatDate 设计不佳且早已过时。现代的 API 更好用。 Arvind Kumar Avinash 的答案的后半部分向您展示了如何做。我没有理由重复它。是的,Arvind 的代码 确实 解决了您的问题。

你的代码出了什么问题?

据说您的问题是没有为格式化程序提供 English-speaking 语言环境。这是部分事实,但它并不能完全解释为什么 07:05 PM 被转换为 07:05,而正确的转换会给出 19:05.

您的第一个输入格式化程序(具有模式 hh:mm aa 的格式化程序)解析失败,因为它使用了一种语言,其中 PM 会被称为其他语言。接下来是第二个格式化程序,使用模式 HH:mm 成功 解析字符串。令人惊讶,不是吗?我认为它不一定解析整个字符串是 SimpleDateFormat 的许多令人困惑的特征之一。它将 07:05 部分解析为小时 和分钟。然后它忽略了字符串的其余部分。这样你得到的结果 07:05 是不正确的,而不是正确的 19:05。这只是您根本不应该使用 SimpleDateFormat 的原因之一。

链接

  • Oracle tutorial: Date Time 解释如何使用 java.time.
  • 相关问题:
    • about locale for parsing AM an PM. I obviously recommend 使用 java.time.
    • SimpleDateFormat parse(string str) doesn't throw an exception when str = 2011/12/12aaaaaaaaa? about SimpleDateFormat not parsing the entire string. Be inspired by the answer by David使用java.time简单直接的解决问题
    • ,我觉得和你的差不多。
    • Conversion from 12 hours time to 24 hours time in java. I recommend the answer by Cloud 使用 java.time.