206

I am new to Java, usually work with PHP.

I am trying to convert this string:

Mon Mar 14 16:02:37 GMT 2011

Into a Calendar Object so that I can easily pull the Year and Month like this:

String yearAndMonth = cal.get(Calendar.YEAR)+cal.get(Calendar.MONTH);

Would it be a bad idea to parse it manually? Using a substring method?

Any advice would help thanks!

Azhar Bandri
  • 892
  • 1
  • 14
  • 27
Doug Molineux
  • 12,283
  • 25
  • 92
  • 144
  • Possible duplicate of [How to convert a date String to a Date or Calendar object?](http://stackoverflow.com/questions/43802/how-to-convert-a-date-string-to-a-date-or-calendar-object) – Twonky Apr 12 '17 at 07:35

8 Answers8

454
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
cal.setTime(sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done

note: set Locale according to your environment/requirement


See Also

Shabbir Dhangot
  • 8,954
  • 10
  • 58
  • 80
jmj
  • 237,923
  • 42
  • 401
  • 438
  • http://www.onlineconversion.com/unix_time.htm. This is online timestamp converter. The value which is calculated by java code and this online convert gets differ. Why?? Can u pls go through this. Thanks :) – Sachin J Oct 05 '12 at 09:47
  • 8
    Note that this looses the timezone information. The Calendar object will have the system default TimeZone not the parsed one. – Cristian Vrabie Aug 20 '13 at 15:22
  • 1
    This should not be the top/accepted answer any more. Since Java 8 is already out for more than 4 years the answer should be updated to mention `java.time`. This Q/A comes up pretty prominent on google. – Scolytus Oct 04 '18 at 10:16
26

tl;dr

The modern approach uses the java.time classes.

YearMonth.from(
    ZonedDateTime.parse( 
        "Mon Mar 14 16:02:37 GMT 2011" , 
        DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" )
     )
).toString()

2011-03

Avoid legacy date-time classes

The modern way is with java.time classes. The old date-time classes such as Calendar have proven to be poorly-designed, confusing, and troublesome.

Define a custom formatter to match your string input.

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );

Parse as a ZonedDateTime.

ZonedDateTime zdt = ZonedDateTime.parse( input , f );

You are interested in the year and month. The java.time classes include YearMonth class for that purpose.

YearMonth ym = YearMonth.from( zdt );

You can interrogate for the year and month numbers if needed.

int year = ym.getYear();
int month = ym.getMonthValue();

But the toString method generates a string in standard ISO 8601 format.

String output = ym.toString();

Put this all together.

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );
YearMonth ym = YearMonth.from( zdt );
int year = ym.getYear();
int month = ym.getMonthValue();

Dump to console.

System.out.println( "input: " + input );
System.out.println( "zdt: " + zdt );
System.out.println( "ym: " + ym );

input: Mon Mar 14 16:02:37 GMT 2011

zdt: 2011-03-14T16:02:37Z[GMT]

ym: 2011-03

Live code

See this code running in IdeOne.com.

Conversion

If you must have a Calendar object, you can convert to a GregorianCalendar using new methods added to the old classes.

GregorianCalendar gc = GregorianCalendar.from( zdt );

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.

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

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

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. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Just to add to this, one can access the Day from the `ZonedDateTime` Object. For example: `zdt.getDayOfMonth()` (returns `int`), `zdt.getDayOfYear()` (returns `int`), or `zdt.getDayOfWeek()` (returns `java.time.DayOfWeek`). – OscuroAA Aug 04 '22 at 01:47
14

Well, I think it would be a bad idea to replicate the code which is already present in classes like SimpleDateFormat.

On the other hand, personally I'd suggest avoiding Calendar and Date entirely if you can, and using Joda Time instead, as a far better designed date and time API. For example, you need to be aware that SimpleDateFormat is not thread-safe, so you either need thread-locals, synchronization, or a new instance each time you use it. Joda parsers and formatters are thread-safe.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks for your input, I will certainly look into using Joda in the future, looks like it can be very useful – Doug Molineux Mar 14 '11 at 16:18
  • @Jon Skeet Joda will not deserialize in Android. Joda is worth little unless you have no need to save dates and time. – Frank Zappa Feb 16 '17 at 20:47
  • @FrankZappa: I'd disagree with that - you can do all your date/time *calculations* in Joda Time, but then convert to other types (maybe just strings for simplicity) for serialization purposes. – Jon Skeet Feb 16 '17 at 22:12
  • Sorry, had to downvote, the answer is too old, it's outdated to be the highest ranking answer. Today `java.time` is the way to go, Basil Bourque provided an excellent answer. – Scolytus Oct 01 '18 at 13:54
  • 2
    @Scolytus: The top (and accepted) answer has 332 votes compared with 10 on this one. I think if you go round downvoting every 7+-year-old answer that has a better solution now, you'll run out of downvotes... (I agree that Basil's answer is good, and I've upvoted that.) – Jon Skeet Oct 01 '18 at 20:59
  • @JonSkeet OMG, I'm sorry, I totally got the wrong answer, in fact this was intended for the top/accepted answer. Your answer with Joda time was already a better one. Really sorry! – Scolytus Oct 04 '18 at 10:11
10

No new Calendar needs to be created, SimpleDateFormat already uses a Calendar underneath.

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.EN_US);
Date date = sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done
Calendar cal = sdf.getCalendar();

(I can't comment yet, that's why I created a new answer)

GoGoris
  • 820
  • 8
  • 20
  • 1
    Your solution looks elegant, but has two disadvantages: 1. The JavaDoc doesn't guarantee that the behavior is, as expected. 2. At least for Java 6 you find a path at line 1353 where the calendar-object is cloned. So then then !date.equals(cal.getTime()). – niels Dec 07 '17 at 10:52
6

SimpleDateFormat is great, just note that HH is different from hh when working with hours. HH will return 24 hour based hours and hh will return 12 hour based hours.

For example, the following will return 12 hour time:

SimpleDateFormat sdf = new SimpleDateFormat("hh:mm aa");

While this will return 24 hour time:

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
Philip
  • 503
  • 7
  • 8
6

Parse a time with timezone, Z in pattern is for time zone

String aTime = "2017-10-25T11:39:00+09:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
try {
    Calendar cal = Calendar.getInstance();
    cal.setTime(sdf.parse(aTime));
    Log.i(TAG, "time = " + cal.getTimeInMillis()); 
} catch (ParseException e) {
    e.printStackTrace();
}

Output: it will return the UTC time

1508899140000

enter image description here

If we don't set the time zone in pattern like yyyy-MM-dd'T'HH:mm:ss. SimpleDateFormat will use the time zone which have set in Setting

Linh
  • 57,942
  • 23
  • 262
  • 279
3

Yes it would be bad practice to parse it yourself. Take a look at SimpleDateFormat, it will turn the String into a Date and you can set the Date into a Calendar instance.

John Vint
  • 39,695
  • 7
  • 78
  • 108
1

Simple method:

public Calendar stringToCalendar(String date, String pattern) throws ParseException {
    String DEFAULT_LOCALE_NAME = "pt";
    String DEFAULT_COUNTRY = "BR";
    Locale DEFAULT_LOCALE = new Locale(DEFAULT_LOCALE_NAME, DEFAULT_COUNTRY);
    SimpleDateFormat format = new SimpleDateFormat(pattern, LocaleUtils.DEFAULT_LOCALE);
    Date d = format.parse(date);
    Calendar c = getCalendar();
    c.setTime(d);
    return c;
}
Alberto Cerqueira
  • 1,339
  • 14
  • 18