如何正确格式化日期?

时间:2012-01-20 19:05:34

标签: java date time

下面显示的函数返回日期,例如“2010年9月8日星期六00:00”。但我希望以“yyyy-MM-dd HH:mm”的格式获得日期。这段代码有什么问题?

String date = "2010-08-25";
String time = "00:00";

同样在一台笔记本电脑中输出,例如23:45是11:45。如何准确定义24格式?

private static Date date(final String date,final String time) {
       final Calendar calendar = Calendar.getInstance();
       String[] ymd = date.split("-");
       int year = Integer.parseInt(ymd[0]);
       int month = Integer.parseInt(ymd[1]);
       int day = Integer.parseInt(ymd[2]);
       String[] hm = time.split(":");
       int hour = Integer.parseInt(hm[0]);
       int minute = Integer.parseInt(hm[1]);
       calendar.set(Calendar.YEAR,year);
       calendar.set(Calendar.MONTH,month);
       calendar.set(Calendar.DAY_OF_MONTH,day);
       calendar.set(Calendar.HOUR,hour);
       calendar.set(Calendar.MINUTE,minute);
       SimpleDateFormat dateFormat =  new SimpleDateFormat("yyyy-MM-dd HH:mm");
       Date d = calendar.getTime();
       String dateString= dateFormat.format(d);
       Date result = null;
       try {
            result = (Date)dateFormat.parse(dateString);
       } catch (ParseException e) {
            e.printStackTrace();
       }
       return result;
    }

5 个答案:

答案 0 :(得分:3)

  

此代码有什么问题?

您似乎期望返回的Date对象知道您解析它的格式 - 它没有。这只是一个瞬间。如果您想要特定格式的日期,请使用SimpleDateFormat.format,就这么简单。 (好吧,或者你使用更好的库,例如Joda Time。)

Date值视为int - int只是一个数字;你没有“十六进制中的int”或“十进制中的int”......当你想要格式化它时,你做出了这个决定。 Date也是如此。

(同样,Date与特定日历,时区或区域设置无关。这只是一个瞬间。)

答案 1 :(得分:2)

只需使用SimpleDateFormat

答案 2 :(得分:2)

你是如何打印出来的?如果您只是使用System.out.println(date("2010-08-25", "00:00"),则可能会获得Sat Sep 8 00:00 PDT 2010,具体取决于您正在运行的计算机中的当前日期时间格式设置。但你能做的就是:

Date d = date("2010-08-25", "00:00");
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm").format(d));

只是好奇为什么你要为整个过程烦恼,因为你可以通过连接你的初始日期和时间字符串来简单地得到结果。

答案 3 :(得分:2)

标准库不支持格式化的 Date-Time 对象。

<块引用>

下面显示的函数返回日期,例如“太平洋夏令时间 9 月 8 日星期六 00:00 2010"。但我希望得到以下格式的日期 “yyyy-MM-dd HH:mm”。

标准日期时间类没有任何属性来保存格式信息。即使某些库或自定义类承诺这样做,它也违反了 Single Responsibility Principle。 Date-Time 对象应该存储有关日期、时间、时区等的信息,与格式无关。以所需格式表示日期时间对象的唯一方法是使用日期时间解析/格式化类型将其格式化为 String

  • 对于现代日期时间 APIjava.time.format.DateTimeFormatter
  • 对于旧的 Date-Time APIjava.text.SimpleDateFormat

关于java.util.Date

java.util.Date 对象仅表示自称为“纪元”的标准基准时间(即 1970 年 1 月 1 日 00 日)以来的 毫秒 数: 00:00 GMT(或UTC)。由于它不保存任何时区信息,它的 toString 函数应用 JVM 的时区返回一个 String 格式,EEE MMM dd HH:mm:ss zzz yyyy,从这个 毫秒值。要以不同的格式和时区获取 String 对象的 java.util.Date 表示,您需要将 SimpleDateFormat 与所需的格式和适用的时区一起使用,例如

Date date = new Date(); // In your case, it will be Date date = date("2010-08-25", "00:00");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH);
// sdf.setTimeZone(TimeZone.getTimeZone("America/New_York")); // For a timezone-specific value
String strDate = sdf.format(date);
System.out.println(strDate);

您的函数 Date date(String, String) 容易出错。

您可以简单地将日期和时间字符串与分隔符组合,然后使用 SimpleDateFormat 来解析组合字符串,例如您可以将它们与作为分隔符的空白字符组合在一起,以使用与上面显示的相同的 SimpleDateFormat

private static Date date(final String date, final String time) throws ParseException {
    return sdf.parse(date + " " + time);
}

请注意,使用分隔符不是强制性要求,例如您可以将其设为 sdf.parse(date + time),但为此,您需要将 sdf 的格式更改为 yyyy-MM-ddHH:mm,这虽然正确,但可能看起来令人困惑。

演示:

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

public class Main {
    static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH);

    public static void main(String[] args) throws ParseException {
        Date date = date("2010-08-25", "00:00");
        String strDate = sdf.format(date);
        System.out.println(strDate);
    }

    private static Date date(final String date, final String time) throws ParseException {
        return sdf.parse(date + " " + time);
    }
}

输出:

2010-08-25 00:00

ONLINE DEMO

切换到 java.time API。

java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*

使用 java.time(现代日期时间 API)的解决方案:

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

public class Main {
    public static void main(String[] args) {
        LocalDateTime ldt = localDateTime("2010-08-25", "00:00");
        // Default format i.e. the value of ldt.toString()
        System.out.println(ldt);

        // Custom format
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm", Locale.ENGLISH);
        String strDate = dtf.format(ldt);
        System.out.println(strDate);
    }

    private static LocalDateTime localDateTime(final String date, final String time) {
        return LocalDateTime.of(LocalDate.parse(date), LocalTime.parse(time));
    }
}

输出:

2010-08-25T00:00
2010-08-25 00:00

ONLINE DEMO

您一定注意到我没有使用 DateTimeFormatter 来解析 String dateString time。这是因为您的日期和时间字符串符合 ISO 8601 标准。现代日期时间 API 基于 ISO 8601,只要日期时间字符串符合 ISO 8601 标准,就不需要明确使用 DateTimeFormatter 对象。

Trail: Date Time 了解有关现代 Date-Time API 的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

答案 4 :(得分:0)

我很惊讶您在不同的计算机上获得了不同的日期输出。理论上,SimpleDateFormat模式“H”应该以24h格式输出日期。你是晚上11点45分还是上午11点45分?

虽然它不应该影响结果,但SimpleDateFormat和Calendar依赖于Locale,因此您可以尝试指定要使用的确切语言环境(Locale.US),看看是否有任何区别。

作为最终建议,如果您愿意,您也可以尝试使用Joda-Time库(DateTime)代替日期操作。它使得使用日期对象变得更加容易。

    DateTime date = new DateTime( 1991, 10, 13, 23, 39, 0);
    String dateString = new SimpleDateFormat("yyyy-MM-dd HH:mm").format( date.toDate());
    DateTime newDate = DateTime.parse( dateString, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm"));