将java.util.Date转换为字符串

460

我想在Java中将java.util.Date对象转换为String

格式为2010-05-30 22:15:52


2
类似问题:https://dev59.com/L2445IYBdhLWcg3wnroi - Vadzim
@harschware FYI,Joda-Time 项目现已进入维护模式,团队建议迁移到java.time类。请参阅Oracle的教程 - Basil Bourque
1
我建议您在2019年不要使用Date类。该类设计不佳且已经过时。相反,使用Instant或来自java.time,现代Java日期和时间API的其他类。 - Ole V.V.
17个回答

840

使用DateFormat#format 方法将 Date 转换为 String

String pattern = "MM/dd/yyyy HH:mm:ss";

// Create an instance of SimpleDateFormat used for formatting 
// the string representation of date according to the chosen pattern
DateFormat df = new SimpleDateFormat(pattern);

// Get the today date using Calendar object.
Date today = Calendar.getInstance().getTime();        
// Using DateFormat format method we can create a string 
// representation of a date with the defined format.
String todayAsString = df.format(today);

// Print the result!
System.out.println("Today is: " + todayAsString);

来源于http://www.kodejava.org/examples/86.html


29
为什么要使用 Calendar 而不是简单的 new Date()?它们有区别吗? - Alexander Malakhov
11
注意:SimpleDateFormat 不是线程安全的。 https://dev59.com/3Ww15IYBdhLWcg3wFHtZ - Zags
25
日历是一个抽象类,日期是具体的。日期对于时区、语言环境或我们从不使用的其他有用信息一无所知。 - nckbrz
37
“MM/dd/yyyy” 格式很愚蠢和有问题,不要使用它。始终使用“dd/MM/yyyy”或“yyyy-MM-dd”。 - SystemParadox
14
@SystemParadox - 这很蠢,但这并不意味着它毫无意义。我被特别要求使用它,因为它符合人们在报告中所期望的格式。(我更喜欢在所有地方使用“yyyy-MM-dd”,但能做什么呢?)。 - Autumn Leonard
显示剩余3条评论

262
Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s = formatter.format(date);

3
来这里复制粘贴,这个回答节省了我的时间,谢谢并点赞。 - bzuo

70

如果您的类路径中包含commons-lang,那么DateFormatUtils是一个非常好用的工具库。

//Formats a date/time into a specific pattern
 DateFormatUtils.format(yourDate, "yyyy-MM-dd HH:mm:SS");

1
需要进行额外的 null 检查。 - Farrukh Chishti

25

简而言之

myUtilDate.toInstant()  // Convert `java.util.Date` to `Instant`.
          .atOffset( ZoneOffset.UTC )  // Transform `Instant` to `OffsetDateTime`.
          .format( DateTimeFormatter.ISO_LOCAL_DATE_TIME )  // Generate a String.
          .replace( "T" , " " )  // Put a SPACE in the middle.

2014年11月14日14:05:09

java.time

现代方法是使用java.time类,这些类现在取代了令人烦恼的旧的遗留日期时间类。
首先将你的java.util.Date转换为Instant。Instant类表示时间线上的一个时刻,在UTC具有纳秒的分辨率(最多九位(9)小数位)。
与java.time的转换是通过添加到旧类中的新方法来执行的。
Instant instant = myUtilDate.toInstant();

你的java.util.Datejava.time.Instant都在UTC中。如果你想以UTC格式查看日期和时间,那就这么做吧。调用toString方法生成符合ISO 8601标准格式的字符串。
String output = instant.toString();  

2014年11月14日14:05:09 UTC时间

对于其他格式,您需要将Instant转换为更灵活的OffsetDateTime

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC );

odt.toString(): 2020-05-01T21:25:35.957Z

请查看 IdeOne.com 上的代码实时运行

要获得所需格式的字符串,请指定DateTimeFormatter。您可以指定自定义格式,但我建议使用预定义的格式之一(ISO_LOCAL_DATE_TIME),并将其输出中的T替换为空格。

String output = odt.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME )
                   .replace( "T" , " " );

2014年11月14日14:05:09

顺便提一下,我不建议使用这种格式,其中故意丢失偏移量-来自UTC或时区信息。这会导致该字符串的日期时间值的含义不明确。

此外,要注意数据丢失,因为你的字符串表示的日期时间值忽略了任何小数秒(实际上被截断了)。

要通过某个特定地区的挂钟时间观察同一时刻,请应用ZoneId获取ZonedDateTime

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

zdt.toString(): 2014-11-14T14:05:09-05:00[America/Montreal]

为了生成格式化的字符串,做法与上面相同,只需将odt替换为zdt即可。

String output = zdt.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME )
                   .replace( "T" , " " );

如果要执行这段代码很多次,您可能希望更加高效地避免调用 String::replace。去掉这个调用也会使您的代码更短。如果需要,可以在自己的 DateTimeFormatter 对象中指定自己的格式化模式。将此实例缓存为常量或成员以便重用。
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" );  // Data-loss: Dropping any fractional second.

通过传递该实例来应用该格式化程序。

String output = zdt.format( f );

关于java.time

java.time框架内置于Java 8及更高版本中。这些类替代了老旧的日期时间类,如java.util.Date, .Calendar, 和java.text.SimpleDateFormat

Joda-Time项目现在处于维护模式,建议迁移到java.time。

要了解更多信息,请参阅Oracle教程。并在Stack Overflow上搜索许多示例和解释。

许多java.time功能在ThreeTen-Backport中向Java 6和7回溯,并在ThreeTenABP中进一步适应Android(请参见如何使用...)。 ThreeTen-Extra项目通过添加额外的类来扩展java.time。该项目是java.time可能未来添加的潜在试验场。

以下是使用Java 8 Time API格式化的代码示例:https://dev59.com/cG025IYBdhLWcg3w_bCr#43457343 - Vadzim
这段代码无法运行。 OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ); odt.toString(): 2014-11-14T14:05:09+00:00 是否有新的Java 8代码可以获得相同的格式2014-11-14T14:05:09+00:00?谢谢。 - Bob Bolden
@BobBolden 你是正确的,默认情况下使用 Z 而不是 +00:00。我已经修改了回答,谢谢。FYI,它们的含义相同:Z,发音为“Zulu”,表示零小时-分钟-秒的偏移量,与 +00:00 相同。 [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)标准支持这两种样式。 - Basil Bourque
@BasilBourque 抱歉,这不太清楚。我有Java 8,但根本没有instant.atOffset()。您能否建议在Java 8中应该使用什么正确的代码才能获得完全相同的格式2014-11-14T14:05:09+00:00而不需要instant.atOffset()?我有点迷失了:( - Bob Bolden
@BobBolden 在Java 8的Instant类中确实有一个atOffset方法。请参阅Javadoc:Instant::atOffset。在Java 8中,像Instant.now().atOffset( ZoneOffset.UTC ).toString()这样的调用将运行。检查您的import语句。验证您的IDE /项目设置为运行Java 8或更高版本,而不是早期版本的Java。在IdeOne.com上查看代码实时运行:https://ideone.com/2Vm2O5 - Basil Bourque

24

普通Java中的备选一行代码:

String.format("The date: %tY-%tm-%td", date, date, date);

String.format("The date: %1$tY-%1$tm-%1$td", date);

String.format("Time with tz: %tY-%<tm-%<td %<tH:%<tM:%<tS.%<tL%<tz", date);

String.format("The date and time in ISO format: %tF %<tT", date);

这里使用格式化程序相对索引,而不是SimpleDateFormat,后者是线程不安全的,顺便说一句。
稍微有些重复,但只需要一个语句。在某些情况下可能很方便。

1
这是天才。在受限环境下有更好的性能。 - Ruslan
对于初学者:import java.util.Date; 并声明 Date date= new Date(); 以使此代码示例完整。如果从问题中还不明显的话。 - AmigoJack

9

为什么不使用Joda (org.joda.time.DateTime)呢? 它基本上是一个一行代码。

Date currentDate = GregorianCalendar.getInstance().getTime();
String output = new DateTime( currentDate ).toString("yyyy-MM-dd HH:mm:ss");

// output: 2014-11-14 14:05:09

我建议同时传递一个DateTimeZone,而不是将JVM的当前默认时区分配给DateTime对象。new DateTime(currentDate, DateTimeZone.forID("America/Montreal")) - Basil Bourque

7
在一次操作中;) 获取日期
String date = new SimpleDateFormat("yyyy-MM-dd",   Locale.getDefault()).format(new Date());

获取时间

String time = new SimpleDateFormat("hh:mm", Locale.getDefault()).format(new Date());

获取日期和时间

String dateTime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.getDefaut()).format(new Date());

愉快的编程 :)


3
FYI,像java.util.Datejava.util.Calendarjava.text.SimpleDateFormat之类令人头疼的旧日期时间类现在已经过时,被内置于Java 8和Java 9中的java.time类所取代。请参见Oracle的教程 - Basil Bourque

7

“kk” 有特殊作用吗?我认为 Eric 想要使用24小时制。 - Charlie Salts
2
是的,这里指的是一天中的小时(1-24),但这可能不是OP所需要的。HH(0-23)更为常见。 - BalusC
1
@Cahrlie Salts kk 的范围是1-24,而 HH 的范围是0-23,我假设他想要1-24可能有点冒昧。 @BalusC DateFormat对象既可以解析也可以格式化。 - pickypg
我不明白你最后一条评论的相关性。我的评论是给Charlie的。 - BalusC
我习惯于使用 .Net 格式,其中 HH 表示 24 小时制,hh 表示上午/下午。因此这让我感到困惑。 - Charlie Salts
@BalusC 在它被编辑或删除之前,有人提到我的解决方案没有解决 OP 的问题。 - pickypg

5
public static String formateDate(String dateString) {
    Date date;
    String formattedDate = "";
    try {
        date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss",Locale.getDefault()).parse(dateString);
        formattedDate = new SimpleDateFormat("dd/MM/yyyy",Locale.getDefault()).format(date);
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return formattedDate;
}

4
如果你只需要从日期中获取时间,你可以使用字符串的功能。
Date test = new Date();
String dayString = test.toString();
String timeString = dayString.substring( 11 , 19 );

这将自动切掉字符串的时间部分,并将其保存在timeString中。


这可能会因不同的语言环境而出现问题。 - Vadzim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接