0

I have a string with gmt date value and -06:00 at end. What is best way to convert this to CST? I looked at other questions but none of them have -06:00 at end to answer my question.

This is what I tried and it errors out as java.text.ParseException: Unparseable date: "2015-02-19T11:50:09.5953377-06:00"

 private DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss:SSSSSSS'Z'");
    private DateFormat gmtFormat = new SimpleDateFormat();
    private TimeZone cstTime = TimeZone.getTimeZone("CST");

    gmtFormat.setTimeZone(cstTime);
    sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
    try {
                System.out.println("cst start date is " + gmtFormat.format("2015-02-19T11:50:09.5953377-06:00"));
            } catch (ParseException e) {
                e.printStackTrace();
            }
rVr
  • 1,331
  • 8
  • 11

2 Answers2

0

I've run into similar problems before, where I was actually getting dates in 3 different iso formats like that, and was pretty frustrated with it... This isn't pretty, but it may help point you in the right direction...

The 3 formats I was getting the info in:

private static final String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
private static final String ISO_FORMAT2 = "yyyy-MM-dd'T'HH:mm:ss'Z'";
private static final String ISO_FORMAT3 = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";

Actually attempting to parse them (without having to figure out the correct type beforehand, returning a new Date Object in the event all 3 failed so shit doesn't crash because of a damn date formatting exception):

public static Date parseIso(String date){
    SimpleDateFormat sdf = new SimpleDateFormat(ISO_FORMAT, Locale.US);
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

    try {
        return sdf.parse(date);
    } 
    catch (ParseException e) {
        Log.g(TAG, "Failed 1st date parse with " + ISO_FORMAT + " for " + date);

        sdf = new SimpleDateFormat(ISO_FORMAT2, Locale.US);
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

        try {
            return sdf.parse(date);
        } 
        catch (ParseException e2) {
            Log.g(TAG, "Failed 2nd date parse with " + ISO_FORMAT2 + " for " + date);

            sdf = new SimpleDateFormat(ISO_FORMAT3, Locale.US);
            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

            try {
                return sdf.parse(date);
            } 
            catch (ParseException e3) {
                Log.g(TAG, "Failed 3rd date parse with " + ISO_FORMAT3 + " for " + date);                   
            }
        }
    }
    return new Date();
}

And then for actually converting that date to a localized date:

public static String format(long mils, String format){
    return format(getInstance(mils), format);
}

public static String format(Calendar calendar, String format){
    SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

    return sdf.format(new Date(calendar.getTime().getTime() + TimeZone.getDefault().getOffset(new Date().getTime())));
}

public static Calendar getInstance(long timeInMils){
    Calendar cal = Calendar.getInstance();
    cal.setTimeZone(TimeZone.getTimeZone("UTC"));
    cal.setTimeInMillis(timeInMils);
    return cal;
}

So now you can basically call

CalendarHelper.format(myDateObject.getTime(), "MMM dd, yyyy");

and it will return the localized, formatted date from the original UTC date you received.

Again, not pretty, but I hope this can point you in the right direction for converting between the UTC and client's time zone. Best of luck~

PS. I think ISO_FORMAT_3 is the one that will actually help you. I guess I probably could have started with that information, but I'm not a bright man.

Cruceo
  • 6,763
  • 2
  • 31
  • 52
0

ISO 8601

You seem to misunderstand the meaning of the input string, 2015-02-19T11:50:09.5953377-06:00. You do not have a "gmt date value".

That format appears to be the standard ISO 8601 format.

  • The T in the middle separates the date portion from the time-of-day portion.
  • The -06:00 at the end is an offset from UTC. It means "the date-time value shown here is six hours behind UTC".

CST

So, if by CST you mean Central Time Zone (some of the middle parts of the Americas continents), then you need have no conversion to perform. That string with the time 11:50 means "almost noon in Illinois, Arkansas, and Louisiana". If you add 6 hours to 11:50, you would learn the UTC (GMT) date-time at that same moment: 17:50 on same date.

Avoid 3-4 Letter Codes

By the way, avoid using three or four letter time zone codes such as "CST". Those codes are not standardized nor unique. Many duplicates exist. For example, take CST:

  • Central Standard Time (Americas)
  • China Standard Time
  • Central Standard Time (Australia)
  • Central Summer Time (Australia)
  • Cuba Standard Time

Instead use proper time zones. Most of these are continent plus a slash plus a city/region. Examples: America/Regina, America/Monterrey, and America/Indiana/Knox.

Joda-Time | java.time

The java.util.Date/.Calendar classes are notoriously troublesome. Avoid them.

Use either the Joda-Time library or the new java.time package built into Java 8. The java.time package is inspired by Joda-Time but is re-architected. Each has its own strengths and weaknesses.

Both Joda-Time and java.time use ISO 8601 formats as their defaults for both parsing and generating string representations of date-time values.

As this Question is really a duplicate with hundreds of such Questions and Answers already posted, I'll give just one quick example.

String input = "2015-02-19T11:50:09.5953377-06:00";
DateTimeZone zoneAmerica_Regina = DateTimeZone.forID( "America/Regina" );
DateTime dateTimeAmericaRegina = new DateTime( input, zoneAmerica_Regina ); 
DateTime dateTimeLosAngeles = dateTimeAmericaRegina.withZone( DateTimeZone.forID( "America/Los_Angeles" ) );
DateTime dateTimeUtc = dateTimeAmericaRegina.withZone( DateTimeZone.UTC );

Fractional Seconds

Your input string has a very small fraction of a second. Joda-Time (like java.util.Date) handles only millisecond resolution — three digits after the decimal point. The java.item package handles nanosecond resolution. Some systems use microsecond resolution, such as database like Postgres. And some systems follow the old Unix convention of whole seconds.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154