简体   繁体   English

将日期字符串从ISO 8601格式转换为另一种格式

[英]Convert date string from ISO 8601 format to another

i have this piece of code , where i am trying to convert a date string from one format to another, and finally i want the date object again. 我有这段代码,我试图将日期字符串从一种格式转换为另一种格式,最后我再次想要日期对象。

            String dateString = "2014-10-04";
    SimpleDateFormat oldFormatter = new SimpleDateFormat("yyyy-MM-dd");
    Date parsedDate = oldFormatter.parse(dateString);
    SimpleDateFormat newFormatter = new SimpleDateFormat("dd-MMM-yyyy");
    String convertDateStr = newFormatter.format(parsedDate);
    Date convertedDate = newFormatter.parse(convertDateStr);

when i was testing above code with dateString value as "2014-10-04", the above code executes properly but the convertedDate format changed to "Sat Oct 04 00:00:00 IST 2014" instead of "dd-MMM-yyyy" format. 当我使用dateString值作为“2014-10-04”测试上面的代码时,上面的代码正确执行但convertDate格式改为“Sat Oct 04 00:00:00 IST 2014”而不是“dd-MMM-yyyy”格式。

i have functionality like i have two dates with different format, and need to get difference in days remaining while comparing, so i need to convert one date format to other date before getting the difference in number of days. 我有这样的功能,我有两个不同格式的日期,并需要在比较时剩余的天数有所不同,所以我需要将一种日期格式转换为其他日期,然后才能获得天数的差异。

EDIT - is there an alternate option to convert datestring to a specified format and get back date object with converted format 编辑 - 是否有一个替代选项将datetring转换为指定的格式,并获得转换格式的日期对象

A Date object doesn't have format built into it, that is what the SimpleDateFormat does. Date对象没有内置格式,这就是SimpleDateFormat所做的。 When you convert convertDateStr back into a Date object, you've lost the formatting. convertDateStr转换回Date对象时,您已经丢失了格式。

Run these after your block of code and you'll see what I mean. 在您的代码块之后运行这些代码,您将看到我的意思。

    System.out.println(convertedDate);
    System.out.println(newFormatter.format(convertedDate));

tl;dr TL;博士

LocalDate.parse(            // Represent a date-only value with a date-only class.
    "2014-10-04"            // Inputs in standard ISO 8601 format are parsed by default. No need to specify a formatting pattern.
)                           // Returns a `LocalDate` object. Do not conflate a date-time object with a String that represents its value. A `LocalDate` has no “format”.
.format(                    // Generate a String representing the `LocalDate` object’s value. 
    DateTimeFormatter.ofPattern( "dd-MMM-uuuu" , Locale.US )  // Define your custom formatting pattern. Specify `Locale` for human language and cultural norms used in localization.
)                           // Return a String.

java.time java.time

The modern approach uses java.time classes that supplanted the troublesome old legacy date-time classes such as Date / Calendar / SimpleDateFormat . 现代方法使用java.time类来取代麻烦的旧遗留日期时间类,例如Date / Calendar / SimpleDateFormat

Use a date-only class for date-only values, rather than a date+time class. 将仅限日期的类用于仅限日期的值,而不是日期+时间类。 The LocalDate class represents a date-only value without time-of-day and without time zone. LocalDate类表示没有时间且没有时区的仅日期值。

Your input string happens to comply with standard ISO 8601 format. 您的输入字符串恰好符合标准ISO 8601格式。 The java.time classes use ISO 8601 formats by default when parsing/generating strings. 在解析/生成字符串时, java.time类默认使用ISO 8601格式。 So no need to specify a formatting pattern. 因此无需指定格式化模式。

String input  = "2014-10-04" ;
LocalDate ld = LocalDate.parse( input ) ;  // No need to specify a formatting pattern for ISO 8601 inputs.

To generate a string representing the LocalDate object's value in a particular format, define the formatting pattern. 要生成表示特定格式的LocalDate对象值的字符串,请定义格式设置模式。 Specify a Locale object to determine the human language and cultural norms used in localizing. 指定Locale对象以确定本地化中使用的人类语言和文化规范。

Locale locale = Locale.US ; 
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MMM-uuuu" , locale ) ;
String output = ld.format( f ) ;

04-Oct-2014 04 - 10月2014


About java.time 关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat . 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes. 现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial . 要了解更多信息,请参阅Oracle教程 And search Stack Overflow for many examples and explanations. 并搜索Stack Overflow以获取许多示例和解释。 Specification is JSR 310 . 规范是JSR 310

You may exchange java.time objects directly with your database. 您可以直接与数据库交换java.time对象。 Use a JDBC driver compliant with JDBC 4.2 or later. 使用符合JDBC 4.2或更高版本的JDBC驱动程序 No need for strings, no need for java.sql.* classes. 不需要字符串,不需要java.sql.*类。

Where to obtain the java.time classes? 从哪里获取java.time类?

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time. 该项目是未来可能添加到java.time的试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more . 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

The Date object doesn't store a format for the date. Date对象不存储Date的格式。 That output you are seeing is simply the result of its toString method. 您看到的输出只是其toString方法的结果。 If you want a date in a specific format, you must always use a formatter to get the string version of the date in the format you want. 如果您想要特定格式的日期,则必须始终使用格式化程序以所需格式获取日期的字符串版本。

Joda-Time 乔达时间

UPDATE: The Joda-Time project is now in maintenance mode , with the team advising migration to the java.time classes. 更新: Joda-Time项目现在处于维护模式 ,团队建议迁移到java.time类。 This Answer left intact for history. 这个答案完整地保留了历史。

As explained in the correct answer by forgivenson and in many other questions and answers found by searching StackOverflow for "java date format" or "java date parse" or such: 正如forgivenson正确答案中所解释的那样,以及通过在StackOverflow中搜索“java日期格式”或“java日期解析”等找到的许多其他问题和答案:

  • A java.util.Date object has no format. java.util.Date对象没有格式。 A juDate is not text. juDate不是文本。 A juDate does not contain a String. juDate不包含String。 A juDate object contains a number of milliseconds since the Unix epoch (ignoring Leap Seconds). juDate对象包含自Unix纪元以来的毫秒数(忽略闰秒)。
  • You can generate a String representation of the date-time value of a java.util.Date by either calling its toString implementation or by using a formatter. 您可以生成通过调用它的一个java.util.Date的日期时间值的字符串表示toString实现,或者通过使用格式。
  • The toString method of java.util.Date is confusing in that it applies the JVM's default time zone. java.util.Date的toString方法令人困惑,因为它应用了JVM的默认时区。 The result implies a juDate has a time zone when in fact it does not. 结果意味着juDate有一个时区,实际上它没有。
  • The java.util.Date and .Calendar classes are notoriously troublesome. 众所周知,java.util.Date和.Calendar类很麻烦。 Avoid them. 避免他们。 Use a decent date-time library such as Joda-Time or the new java.time package bundled in Java 8. 使用一个体面的日期时间库,如Joda-Time或Java 8中捆绑的新java.time包。
  • Your code ignores the crucial issue of time zones. 您的代码忽略了时区的关键问题。 A java.util.Date has a date and a time, and so you need to pay attention to time zones. java.util.Date有日期和时间,因此您需要注意时区。
  • Joda-Time and java.time both use formatting defined by the ISO 8601 standard as their default. Joda-Time和java.time都使用ISO 8601标准定义的格式作为默认值。 You may define your own formats as well, or use localized formats. 您也可以定义自己的格式,或使用本地化格式。

So your phrase "get back date object with converted format" is a contradiction. 所以你的短语“用转换后的格式取回日期对象”是一个矛盾。 A date-time object (whether java.util.Date or Joda-Time or java.time) has no format . 日期时间对象(无论是java.util.Date还是Joda-Time或java.time) 没有格式 You are confusing the string representation generated from a date-time object with the date-time object itself. 你混淆了与日期时间对象本身的日期,时间对象生成的字符串表示。

Example code using Joda-Time 2.3… 使用Joda-Time 2.3的示例代码...

String input = "2014-10-04";

DateTimeZone timeZoneIndia = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeIndia = new DateTime( input, timeZoneIndia ); // Defaults to beginning of the day.
DateTime dateTimeUtc = dateTimeIndia.withZone( DateTimeZone.UTC );
DateTime octoberSecond = new DateTime( 2014, 10, 2, 1, 2, 3, timeZoneIndia ).withTimeAtStartOfDay();

DateTimeFormatter formatter_Iso = ISODateTimeFormat.date();
String dateTimeIndiaAsStringIso = formatter_Iso.print( dateTimeIndia );

DateTimeFormatter formatter_Dmy = DateTimeFormat.forPattern( "dd-MM-yyyy" );
String dateTimeIndiaAsStringDmy = formatter_Dmy.print( dateTimeIndia );
DateTime dateTimeAgain = formatter_Dmy.withZone( timeZoneIndia ).parseDateTime( dateTimeIndiaAsStringDmy ); // Defaults to beginning of the day.

DateTimeFormatter formatter_Québécois = DateTimeFormat.forStyle( "FF" ).withLocale( Locale.CANADA_FRENCH );
String dateTimeIndiaAsStringQuébécois = formatter_Québécois.print( dateTimeIndia );

int daysBetween = Days.daysBetween( octoberSecond, dateTimeIndia ).getDays();
Interval interval = new Interval( octoberSecond, dateTimeIndia );
Period period = interval.toPeriod();

java.util.Date date = dateTimeIndia.toDate();

input: 2014-10-04
dateTimeIndia: 2014-10-04T00:00:00.000+05:30
dateTimeUtc: 2014-10-03T18:30:00.000Z
octoberSecond: 2014-10-02T00:00:00.000+05:30
dateTimeIndiaAsStringIso: 2014-10-04
dateTimeIndiaAsStringDmy: 04-10-2014
dateTimeAgain: 2014-10-04T00:00:00.000+05:30
dateTimeIndiaAsStringQuébécois: samedi 4 octobre 2014 0 h 00 IST
daysBetween: 2
interval: 2014-10-02T00:00:00.000+05:30/2014-10-04T00:00:00.000+05:30
period: P2D
date: Fri Oct 03 11:30:00 PDT 2014

Dump to console… 转储到控制台......

System.out.println( "input: " + input );
System.out.println( "dateTimeIndia: " + dateTimeIndia );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "octoberSecond: " + octoberSecond );
System.out.println( "dateTimeIndiaAsStringIso: " + dateTimeIndiaAsStringIso );
System.out.println( "dateTimeIndiaAsStringDmy: " + dateTimeIndiaAsStringDmy );
System.out.println( "dateTimeAgain: " + dateTimeAgain );
System.out.println( "dateTimeIndiaAsStringQuébécois: " + dateTimeIndiaAsStringQuébécois );
System.out.println( "daysBetween: " + daysBetween );
System.out.println( "interval: " + interval );
System.out.println( "period: " + period );
System.out.println( "date: " + date );  // Applies JVM's default time zone. North America west coast time zone in my case.

When run… 跑的时候......

input: 2014-10-04
dateTimeIndia: 2014-10-04T00:00:00.000+05:30
dateTimeUtc: 2014-10-03T18:30:00.000Z
octoberSecond: 2014-10-02T00:00:00.000+05:30
dateTimeIndiaAsStringIso: 2014-10-04
dateTimeIndiaAsStringDmy: 04-10-2014
dateTimeAgain: 2014-10-04T00:00:00.000+05:30
dateTimeIndiaAsStringQuébécois: samedi 4 octobre 2014 0 h 00 IST
daysBetween: 2
interval: 2014-10-02T00:00:00.000+05:30/2014-10-04T00:00:00.000+05:30
period: P2D
date: Fri Oct 03 11:30:00 PDT 2014
You can use this

    public static Date getDateFromString(String format, String dateStr) {

        DateFormat formatter = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = (Date) formatter.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return date;
    }

    public static String getDate(Date date, String dateFormat) {
        DateFormat formatter = new SimpleDateFormat(dateFormat);
        return formatter.format(date);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM