0

I am trying to reformat a date string using sdf. SDF is decrementing the date by a day. Pointers would be helpful.

java version "1.8.0_31" Input: ChangeDateStringFormat("10-Mar-2015");

Code:

public static String ChangeDateStringFormat (String Input) throws InterruptedException 
{           
    System.out.print("Input Date inside ChangeDateStringFormat : " + Input );

    SimpleDateFormat sdf = new SimpleDateFormat("MMM-dd-yyyy");
    sdf.setTimeZone(TimeZone.getTimeZone("MST"));

    System.out.print(" || Output Date inside ChangeDateStringFormat : " +  sdf.format(new Date(Input)) + "\n");
    return sdf.format(new Date(Input));
}

Output Actual:

Input Date inside ChangeDateStringFormat : 10-Mar-2015 || Output Date inside ChangeDateStringFormat : Mar-09-2015

Output I was Expecting :

Input Date inside ChangeDateStringFormat : 10-Mar-2015 || Output Date inside ChangeDateStringFormat : Mar-10-2015

user2041390
  • 43
  • 1
  • 3
  • 9
  • 2
    As an aside, *please* follow Java naming conventions. It really lowers cognitive dissonance. – Jon Skeet Mar 04 '15 at 14:36
  • Use java.util.Calendar to descrementing the date. – Jens Mar 04 '15 at 14:36
  • 1
    Since you use Java 8, use the new date/time API, please! – fge Mar 04 '15 at 14:37
  • What happens if you take out `setTimeZone(...)`? – ControlAltDel Mar 04 '15 at 14:38
  • 1
    Do not use the deprecated `Date(String)` constructor to parse your input date. Instead use a `DateFormat` that corresponds to your input. – John Bollinger Mar 04 '15 at 14:39
  • You should set your formatter's `Locale` accordingly too, because Mar stands for March in English, Spanish and French, but not Germain (Mär), and quite an awful lot of languages without a Latin alphabet. That is, unless you know your argument will always be formatted according to the system's default Locale. – GPI Mar 04 '15 at 14:41
  • Since you are on Java 8 consider using the new [Date and Time-API](http://java.dzone.com/articles/introducing-new-date-and-time). – Axel Mar 04 '15 at 14:41
  • after commenting : sdf.setTimeZone(TimeZone.getTimeZone("MST")); I am getting the right output : Input Date inside ChangeDateStringFormat : 10-Mar-2015 || Output Date inside ChangeDateStringFormat : Mar-10-2015 Just wondering if that would have ripple effect ? Shouldn't format just change the formatting, and not perform any manipulation of data ? – user2041390 Mar 04 '15 at 14:44

2 Answers2

4

This is the problem:

new Date(Input)

You should not use that. Instead, construct a SimpleDateFormat to parse your input:

import java.text.*;
import java.util.*;

public class Test {
    public static void main(String[] args) throws ParseException {
        System.out.println(convertDateFormat("10-Mar-2015"));
    }

    public static String convertDateFormat(String input) throws ParseException {
        TimeZone zone = TimeZone.getTimeZone("MST");
        SimpleDateFormat inputFormat = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
        inputFormat.setTimeZone(zone);
        SimpleDateFormat outputFormat = new SimpleDateFormat("MMM-dd-yyyy", Locale.US);
        outputFormat.setTimeZone(zone);

        Date date = inputFormat.parse(input);
        return outputFormat.format(date);
    }
}

However:

  • If you're just parsing a date, you'd be better of specifying UTC as the time zone; you don't want to end up with problems due to time zones that switch DST at midnight
  • If you're going to run this code on Java 8 and nothing lower, I'd strongly recommend using java.time instead of Date, Calendar etc.
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Solution using java.time, the modern Date-Time API:

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

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(changeDateStringFormat("10-Mar-2015"));
    }

    static String changeDateStringFormat(String input) {
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("d-MMM-u", Locale.ENGLISH);
        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("MMM-dd-uuuu", Locale.ENGLISH);

        LocalDate date = LocalDate.parse(input, dtfInput);
        
        return date.format(dtfOutput);
    }
}

Output:

Mar-10-2015

ONLINE DEMO

Note: Never use SimpleDateFormat or DateTimeFormatter without a Locale.

Learn more about the modern Date-Time API from Trail: Date Time.

Side Note: Always follow Java naming conventions e.g. the name of your function should be changeDateStringFormat instead of ChangeDateStringFormat and the parameter Input should be named as input.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110