Question

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.

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

Était-ce utile?

La solution

tl;dr

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

The modern approach uses java.time classes that supplanted the troublesome old legacy date-time classes such as 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.

Your input string happens to comply with standard ISO 8601 format. The java.time classes use ISO 8601 formats by default when parsing/generating strings. 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. Specify a Locale object to determine the human language and cultural norms used in localizing.

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

04-Oct-2014


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Autres conseils

A Date object doesn't have format built into it, that is what the SimpleDateFormat does. When you convert convertDateStr back into a Date object, you've lost the formatting.

Run these after your block of code and you'll see what I mean.

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

The Date object doesn't store a format for the date. That output you are seeing is simply the result of its toString method. 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.

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

Joda-Time

UPDATE: The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. 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:

  • A java.util.Date object has no format. A j.u.Date is not text. A j.u.Date does not contain a String. A j.u.Date object contains a number of milliseconds since the Unix epoch (ignoring Leap Seconds).
  • 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.
  • The toString method of java.util.Date is confusing in that it applies the JVM's default time zone. The result implies a j.u.Date has a time zone when in fact it does not.
  • The java.util.Date and .Calendar classes are notoriously troublesome. Avoid them. Use a decent date-time library such as Joda-Time or the new java.time package bundled in Java 8.
  • 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.
  • Joda-Time and java.time both use formatting defined by the ISO 8601 standard as their default. 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. 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…

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top