1

I'v searched for many solutions on SO and didn't find one which worked for me (because of deprecation of some methods etc.). I have a simple problem which can be surely solved within 1 min, but i couldn't find or figure out any solution. I would like to get from string

Wed Sep 23 04:45:21 EDT 2015

another string which should look like

23.09.2015. 04:45:21

I know that first i need to change my string into date and then format that date into string but after 4 hours i kinda give up.

So far i tried many things and nothing works. Code example follows which dont work

String dateobj = "Wed Sep 23 04:45:21 EDT 2015";
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy'T'HH:mm:ss'Z'");
try {
        Date date1 = format.parse(dateobj);
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Any solution?

Thanks in advance

EDIT:

try{
String dateobj = "Wed Sep 23 04:45:21 EDT 2015";
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy"); //
SimpleDateFormat format1 = new SimpleDateFormat("dd.MM.yyyy. HH:mm:ss"); // for display

Date date = format.parse(dateobj); // parse it to date
System.out.print(format1.format(date)); // display the date to format you like
 // the print result is : 23.09.2015. 08:45:21
} catch (Exception e){
System.out.print("error"); }

Code below works only for Wed Sep 23 04:45:21 EDT 2015.

And how to modify this code if i don't have Wed Sep 23 04:45:21 EDT 2015? My date on phone looks like Wed Sep 23 04:45:21 CEST 2015. How to modify code?

KuKeC
  • 4,392
  • 5
  • 31
  • 60

3 Answers3

2

You can use this method:

public static String getFormattedDate(String isoDateTime){

        ISO8601DateFormat df = new ISO8601DateFormat();
        Date date=new Date();
        try {
            date = df.parse(isoDateTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("hh:mm aaa, EEEE, d-MMM-yyyy");
        String dateString=simpleDateFormat.format(date);
        return dateString;
    } 


You need these two helper classes below.
1)ISO8601DateFormat

import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * Created by user on 9/6/2015.
 */
public class ISO8601DateFormat extends java.text.DateFormat {
    private static final long serialVersionUID = 1L;

    // those classes are to try to allow a consistent behavior for hascode/equals and other methods
    private static Calendar CALENDAR = new GregorianCalendar();
    private static NumberFormat NUMBER_FORMAT = new DecimalFormat();

    public ISO8601DateFormat() {
        this.numberFormat = NUMBER_FORMAT;
        this.calendar = CALENDAR;
    }

    @Override
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
        String value = ISO8601Utils.format(date);
        toAppendTo.append(value);
        return toAppendTo;
    }

    @Override
    public Date parse(String source, ParsePosition pos) {
        try {
            return ISO8601Utils.parse(source, pos);
        }
        catch (ParseException e) {
            return null;
        }
    }

    //supply our own parse(String) since pos isn't updated during parsing,
    //but the exception should have the right error offset.
    @Override
    public Date parse(String source) throws ParseException {
        return ISO8601Utils.parse(source, new ParsePosition(0));
    }

    @Override
    public Object clone() {
        /* Jackson calls clone for every call. Since this instance is
         * immutable (and hence thread-safe)
         * we can just return this instance
         */
        return this;
    }

    @Override
    public String toString() { return getClass().getName(); }
}


2)ISO8601DateFormat

import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

/**
 * Created by user on 9/6/2015.
 */
public class ISO8601Utils {
    /**
     * ID to represent the 'GMT' string
     */
    private static final String GMT_ID = "GMT";

    /**
     * The GMT timezone
     */
    private static final TimeZone TIMEZONE_GMT = TimeZone.getTimeZone(GMT_ID);

    /*
    /**********************************************************
    /* Static factories
    /**********************************************************
     */

    /**
     * Accessor for static GMT timezone instance.
     */
    public static TimeZone timeZoneGMT() {
        return TIMEZONE_GMT;
    }

    /*
    /**********************************************************
    /* Formatting
    /**********************************************************
     */

    /**
     * Format a date into 'yyyy-MM-ddThh:mm:ssZ' (GMT timezone, no milliseconds precision)
     *
     * @param date the date to format
     * @return the date formatted as 'yyyy-MM-ddThh:mm:ssZ'
     */
    public static String format(Date date) {
        return format(date, false, TIMEZONE_GMT);
    }

    /**
     * Format a date into 'yyyy-MM-ddThh:mm:ss[.sss]Z' (GMT timezone)
     *
     * @param date the date to format
     * @param millis true to include millis precision otherwise false
     * @return the date formatted as 'yyyy-MM-ddThh:mm:ss[.sss]Z'
     */
    public static String format(Date date, boolean millis) {
        return format(date, millis, TIMEZONE_GMT);
    }

    /**
     * Format date into yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm]
     *
     * @param date the date to format
     * @param millis true to include millis precision otherwise false
     * @param tz timezone to use for the formatting (GMT will produce 'Z')
     * @return the date formatted as yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm]
     */
    public static String format(Date date, boolean millis, TimeZone tz) {
        Calendar calendar = new GregorianCalendar(tz, Locale.ENGLISH);
        calendar.setTime(date);

        // estimate capacity of buffer as close as we can (yeah, that's pedantic ;)
        int capacity = "yyyy-MM-ddThh:mm:ss".length();
        capacity += millis ? ".sss".length() : 0;
        capacity += tz.getRawOffset() == 0 ? "Z".length() : "+hh:mm".length();
        StringBuilder formatted = new StringBuilder(capacity);

        padInt(formatted, calendar.get(Calendar.YEAR), "yyyy".length());
        formatted.append('-');
        padInt(formatted, calendar.get(Calendar.MONTH) + 1, "MM".length());
        formatted.append('-');
        padInt(formatted, calendar.get(Calendar.DAY_OF_MONTH), "dd".length());
        formatted.append('T');
        padInt(formatted, calendar.get(Calendar.HOUR_OF_DAY), "hh".length());
        formatted.append(':');
        padInt(formatted, calendar.get(Calendar.MINUTE), "mm".length());
        formatted.append(':');
        padInt(formatted, calendar.get(Calendar.SECOND), "ss".length());
        if (millis) {
            formatted.append('.');
            padInt(formatted, calendar.get(Calendar.MILLISECOND), "sss".length());
        }

        int offset = tz.getOffset(calendar.getTimeInMillis());
        if (offset != 0) {
            int hours = Math.abs((offset / (60 * 1000)) / 60);
            int minutes = Math.abs((offset / (60 * 1000)) % 60);
            formatted.append(offset < 0 ? '-' : '+');
            padInt(formatted, hours, "hh".length());
            formatted.append(':');
            padInt(formatted, minutes, "mm".length());
        } else {
            formatted.append('Z');
        }

        return formatted.toString();
    }

    /*
    /**********************************************************
    /* Parsing
    /**********************************************************
     */

    /**
     * Parse a date from ISO-8601 formatted string. It expects a format
     * [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]]
     *
     * @param date ISO string to parse in the appropriate format.
     * @param pos The position to start parsing from, updated to where parsing stopped.
     * @return the parsed date
     * @throws ParseException if the date is not in the appropriate format
     */
    public static Date parse(String date, ParsePosition pos) throws ParseException {
        Exception fail = null;
        try {
            int offset = pos.getIndex();

            // extract year
            int year = parseInt(date, offset, offset += 4);
            if (checkOffset(date, offset, '-')) {
                offset += 1;
            }

            // extract month
            int month = parseInt(date, offset, offset += 2);
            if (checkOffset(date, offset, '-')) {
                offset += 1;
            }

            // extract day
            int day = parseInt(date, offset, offset += 2);
            // default time value
            int hour = 0;
            int minutes = 0;
            int seconds = 0;
            int milliseconds = 0; // always use 0 otherwise returned date will include millis of current time

            // if the value has no time component (and no time zone), we are done
            boolean hasT = checkOffset(date, offset, 'T');

            if (!hasT && (date.length() <= offset)) {
                Calendar calendar = new GregorianCalendar(year, month - 1, day);

                pos.setIndex(offset);
                return calendar.getTime();
            }

            if (hasT) {

                // extract hours, minutes, seconds and milliseconds
                hour = parseInt(date, offset += 1, offset += 2);
                if (checkOffset(date, offset, ':')) {
                    offset += 1;
                }

                minutes = parseInt(date, offset, offset += 2);
                if (checkOffset(date, offset, ':')) {
                    offset += 1;
                }
                // second and milliseconds can be optional
                if (date.length() > offset) {
                    char c = date.charAt(offset);
                    if (c != 'Z' && c != '+' && c != '-') {
                        seconds = parseInt(date, offset, offset += 2);
                        // milliseconds can be optional in the format
                        if (checkOffset(date, offset, '.')) {
                            milliseconds = parseInt(date, offset += 1, offset += 3);
                        }
                    }
                }
            }

            // extract timezone
            String timezoneId;
            if (date.length() <= offset) {
                throw new IllegalArgumentException("No time zone indicator");
            }
            char timezoneIndicator = date.charAt(offset);
            if (timezoneIndicator == '+' || timezoneIndicator == '-') {
                String timezoneOffset = date.substring(offset);
                timezoneId = GMT_ID + timezoneOffset;
                offset += timezoneOffset.length();
            } else if (timezoneIndicator == 'Z') {
                timezoneId = GMT_ID;
                offset += 1;
            } else {
                throw new IndexOutOfBoundsException("Invalid time zone indicator " + timezoneIndicator);
            }

            TimeZone timezone = TimeZone.getTimeZone(timezoneId);
            String act = timezone.getID();
            if (!act.equals(timezoneId)) {
                /* 22-Jan-2015, tatu: Looks like canonical version has colons, but we may be given
                 *    one without. If so, don't sweat.
                 *   Yes, very inefficient. Hopefully not hit often.
                 *   If it becomes a perf problem, add 'loose' comparison instead.
                 */
                String cleaned = act.replace(":", "");
                if (!cleaned.equals(timezoneId)) {
                    throw new IndexOutOfBoundsException("Mismatching time zone indicator: "+timezoneId+" given, resolves to "
                            +timezone.getID());
                }
            }

            Calendar calendar = new GregorianCalendar(timezone);
            calendar.setLenient(false);
            calendar.set(Calendar.YEAR, year);
            calendar.set(Calendar.MONTH, month - 1);
            calendar.set(Calendar.DAY_OF_MONTH, day);
            calendar.set(Calendar.HOUR_OF_DAY, hour);
            calendar.set(Calendar.MINUTE, minutes);
            calendar.set(Calendar.SECOND, seconds);
            calendar.set(Calendar.MILLISECOND, milliseconds);

            pos.setIndex(offset);
            return calendar.getTime();
            // If we get a ParseException it'll already have the right message/offset.
            // Other exception types can convert here.
        } catch (IndexOutOfBoundsException e) {
            fail = e;
        } catch (NumberFormatException e) {
            fail = e;
        } catch (IllegalArgumentException e) {
            fail = e;
        }
        String input = (date == null) ? null : ('"' + date + "'");
        String msg = fail.getMessage();
        if (msg == null || msg.isEmpty()) {
            msg = "("+fail.getClass().getName()+")";
        }
        ParseException ex = new ParseException("Failed to parse date [" + input + "]: " + msg, pos.getIndex());
        ex.initCause(fail);
        throw ex;
    }

    /**
     * Check if the expected character exist at the given offset in the value.
     *
     * @param value the string to check at the specified offset
     * @param offset the offset to look for the expected character
     * @param expected the expected character
     * @return true if the expected character exist at the given offset
     */
    private static boolean checkOffset(String value, int offset, char expected) {
        return (offset < value.length()) && (value.charAt(offset) == expected);
    }

    /**
     * Parse an integer located between 2 given offsets in a string
     *
     * @param value the string to parse
     * @param beginIndex the start index for the integer in the string
     * @param endIndex the end index for the integer in the string
     * @return the int
     * @throws NumberFormatException if the value is not a number
     */
    private static int parseInt(String value, int beginIndex, int endIndex) throws NumberFormatException {
        if (beginIndex < 0 || endIndex > value.length() || beginIndex > endIndex) {
            throw new NumberFormatException(value);
        }
        // use same logic as in Integer.parseInt() but less generic we're not supporting negative values
        int i = beginIndex;
        int result = 0;
        int digit;
        if (i < endIndex) {
            digit = Character.digit(value.charAt(i++), 10);
            if (digit < 0) {
                throw new NumberFormatException("Invalid number: " + value);
            }
            result = -digit;
        }
        while (i < endIndex) {
            digit = Character.digit(value.charAt(i++), 10);
            if (digit < 0) {
                throw new NumberFormatException("Invalid number: " + value);
            }
            result *= 10;
            result -= digit;
        }
        return -result;
    }

    /**
     * Zero pad a number to a specified length
     *
     * @param buffer buffer to use for padding
     * @param value the integer value to pad if necessary.
     * @param length the length of the string we should zero pad
     */
    private static void padInt(StringBuilder buffer, int value, int length) {
        String strValue = Integer.toString(value);
        for (int i = length - strValue.length(); i > 0; i--) {
            buffer.append('0');
        }
        buffer.append(strValue);
    }
}


You may delete the code not required
You need to change method SimpleDateFormat parameters to customise your own date. The link below will tell you parameter details:
https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html

AnswerDroid
  • 1,873
  • 2
  • 33
  • 52
2

Your date parsing was throw an exception error because the parse format do not match with the date format. I've corrected some of your code to make it work.

try{
  String dateobj = "Wed Sep 23 04:45:21 EDT 2015";
  SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy"); //
  SimpleDateFormat format1 = new SimpleDateFormat("dd.MM.yyyy. HH:mm:ss"); // for display

  Date date = format.parse(dateobj); // parse it to date
  System.out.print(format1.format(date)); // display the date to format you like
 // the print result is : 23.09.2015. 08:45:21
} catch (Exception e){
  System.out.print("error");
}
cw fei
  • 1,534
  • 1
  • 15
  • 33
  • That i was looking for :) Excellent solution without using any other class/library. Thanks a lot – KuKeC Sep 23 '15 at 11:23
  • And how to modify this code if i don't have `Wed Sep 23 04:45:21 EDT 2015`? My date on phone looks like `Wed Sep 23 04:45:21 CEST 2015`. How to modify code? – KuKeC Sep 28 '15 at 10:38
1
String dateobj = "Wed Sep 23 04:45:21 EDT 2015";
    final DateTimeFormatter formatter = DateTimeFormat.forPattern("EEE MMM d k:m:s z x");
    LocalDateTime obj = LocalDateTime.parse(dateobj, formatter);
    String final_text = obj.getDayOfMonth() + "." + obj.getMonthOfYear() + "." + obj.getYear()
            + ". " + obj.getHourOfDay() + ":" + obj.getMinuteOfHour() + ":" + obj.getSecondOfMinute();

I have used the Joda library to get this.You won't even need to hardcode it like this,the joda library provides multiple timezones and locales so it would directly give you this output.

Locales & Timezones

Formatter

It is a very rich api and you should have a look at it.

Jude Fernandes
  • 7,437
  • 11
  • 53
  • 90