Parse Date String to Some Java Object - java

I am working in a project that reads files and processes data. There I got to work with dates for example:
2012-01-10 23:13:26
January 13, 2012
I found the package Joda, kinda interesting package but don't know if it is the easiest around.
I was able to parse the first example to a DateTime object (Joda) reg-ex and String manipulation. (Ex: by replacing the space by '-' and passing it to constructor.
new DateTime("2012-01-10 23:13:26".replace(' ', '-'))
I guess it worked, but the problem is with the second format. How can I use such an input to extract a an object, preferably a Joda object. I sure can write a function to change the format to what Joda supports, but was wondering if there would be some other way (even some native Java library) to do it.
If there are any thing better than Joda out there, please let me know it as well.
Thank you.

Using Joda-Time, take a look at DateTimeFormat; it allows parsing both kind of date strings that you mention (and almost any other arbitrary formats). If your needs are even more complex, try DateTimeFormatterBuilder.
To parse #1:
DateTimeFormatter f = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTime dateTime = f.parseDateTime("2012-01-10 23:13:26");
Edit: actually LocalDateTime is a more appropriate type for a datetime without a time zone:
LocalDateTime dateTime = f.parseLocalDateTime("2012-01-10 23:13:26");
And for #2:
DateTimeFormatter f = DateTimeFormat.forPattern("MMMM dd, yyyy");
LocalDate localDate = f.parseLocalDate("January 13, 2012");
And yes, Joda-Time is definitely the way to go, as far as Java date & time handling is concerned. :)
As mostly everyone will agree, Joda is an exceptionally user-friendly library. For example, I had never done this kind of parsing with Joda before, but it took me just a few minutes to figure it out from the API and write it.
Update (2015)
If you're on Java 8, in most cases you should simply use java.time instead of Joda-Time. It contains pretty much all the good stuff—or their equivalents—from Joda. For those already familiar with Joda APIs, Stephen Colebourne's Joda-Time to java.time migration guide comes in handy.
Here are java.time versions of above examples.
To parse #1:
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.from(f.parse("2012-01-10 23:13:26"));
You cannot parse this into ZonedDateTime or OffsetDateTime (which are counterparts of Joda's DateTime, used in my original answer), but that kinda makes sense because there's no time zone information in the parsed string.
To parse #2:
DateTimeFormatter f = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
LocalDate localDate = LocalDate.from(f.parse("January 13, 2012"));
Here LocalDate is the most appropriate type to parse into (just like with Joda-Time).

SimpleDateFormat will parse dates into Java Date objects:
http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html
SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); // first example
SimpleDateFormat format2 = new SimpleDateFormat("MMMMM dd,yyyy"); // second example
Date d1 = format1.parse( dateStr1 );
Date d2 = format2.parse( dateStr2 );

I would imagine Joda has something of a Formatter to do this for you. I found this with a quick google search: http://johannburkard.de/blog/programming/java/date-time-parsing-formatting-joda-time.html
DateTimeFormatter parser1 =
DateTimeFormat.forPattern("dd/MMM/yyyy:HH:mm:ss Z");
DateTimeFormatter parser2 =
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm");
DateTime time = parser1.parseDateTime("<data>");
The syntax that is used to evaluate the patterns can be found in X-Zero's link.

JodaTime is largely considered the de-facto standard for date-time processing in Java - they're working to get it added to the next version of the Java library (well, effectively).
For getting JodaTime dates from strings, you're going to want to look into the DateTimeFormat class.

Easiest would be setting up SimpleDateFormat properly as per the format you would expect and use its parse method to give you a Date object

tl;dr
LocalDateTime ldt = LocalDateTime.parse( "2012-01-10 23:13:26".replace( " " , "T" ) );
…and…
LocalDate localDate = LocalDate.parse ( "January 13, 2012" , DateTimeFormatter.ofLocalizedDate ( FormatStyle.LONG ).withLocale ( Locale.US ) );
Details
The Answer by Jonik is basically correct but misses some important issues.
java.time
If there are any thing better than Joda out there, please let me know it as well.
Yes, there is something better, the java.time framework. The Joda-Time team advises migration to java.time as its successor.
The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
Date-time
Your first input is a date plus a time-of-day. It lacks any offset-from-UTC or time zone info, so we parse it as a LocalDateTime object. The “Local…” means any locality, no specific locality. So it is not an actual moment on the timeline but rather just a rough idea about a moment.
To parse the input string 2012-01-10 23:13:26 we can replace the SPACE in the middle with a T to conform with the canonical style for the ISO 8601 standard format of date-time values.
The java.time classes use ISO 8601 formats by default when parsing and generating textual representations of date-time values. So no need to define a parsing pattern.
String input = "2012-01-10 23:13:26".replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( input );
If you know the the intended time zone from the context of this value, apply it to define an actual moment on the timeline.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId );
Dump to console.
System.out.println ( "input: " + input + " | zdt: " + zdt );
input: 2012-01-10T23:13:26 | zdt: 2012-01-10T23:13:26-05:00[America/Montreal]
Date-only
The second of you inputs is a date-only value without time-of-day and without time zone. For that we need the LocalDate class.
I recognize the format of that input as complying with the language (English) and cultural norms of the United States. So no need to specify explicitly a formatting pattern. We can simply ask for a formatter that knows that US format by specifying a Locale. We specify FormatStyle.LONG as appropriate for the length of this format.
String input = "January 13, 2012";
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate ( FormatStyle.LONG ).withLocale ( Locale.US );
LocalDate localDate = LocalDate.parse ( input , formatter );
Dump to console.
System.out.println ( "input: " + input + " | localDate: " + localDate );
input: January 13, 2012 | localDate: 2012-01-13

Related

Setting TimeZone works but seems backwards

I have receiving a date in UTC format but needed to display it in my local timezone (EDT).
Stumbled across the following link :
How to set time zone of a java.util.Date?
Which provide this following answer :
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = isoFormat.parse("2010-05-23T09:01:02");
I added the following line of code :
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
And what do you know it worked.
Trying to understand what happened and it seems a bit backwards.
I would have expected to have to enter EDT to convert from UTC to EDT but it appears to be the opposite.
isoFormat.setTimeZone(TimeZone.getTimeZone("EDT"));
Per the Java Docs for DateFormat it reads ....
And based on the above, it seems like I should be providing the TimeZone I want and not what I am converting from.
Can you explain what am I missing or misinterpreting?
If I enter in UTC, how is it getting EDT to know to convert it correct?
Can anyone fill in the blanks on how I should have know they were asking for the "From" TimeZone?
tl;dr
Use java.time classes.
LocalDateTime
.parse( "2021-07-23T00:00" )
.atOffset( ZoneOffset.UTC )
.atZoneSameInstant( ZoneId.of( "America/Montreal" ) )
.format(
DateTimeFormatter
.ofLocalizedDateTime( FormatStyle.FULL )
.withLocale( Locale.CANADA_FRENCH )
)
Details
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes.
Apparently your input strings are in standard ISO 8601 format. The java.time classes use ISO 8601 formats by default when parsing or generating text. So no need to define a custom formatting pattern.
String input = "2021-07-23T01:23:45" ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
Apparently you know for certain that the input was meant to be seen as a date and time in UTC, that is, having an offset-from-UTC of zero hours-minutes-seconds. If so, educate them publisher of your data to convince them to supply that string with a +00:00 or Z on the end to express that intention.
Meanwhile, we can assign an offset of zero to instantiate a OffsetDateTime.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;
And you apparently want to adjust that date-time to a particular time zone. Apply a ZoneId to get a ZonedDateTime object.
You asked for EDT. Unfortunately, such 2-4 letter codes are not a real time zone. Real time zone names are in format of Continent/Region such as Europe/Paris. Perhaps you meant a time zone such as America/New_York.
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
A java.util.Date object simply represents an instant on the timeline — a wrapper around the number of milliseconds since the UNIX epoch (January 1, 1970, 00:00:00 GMT). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone e.g.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
isoFormat.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
Date date = isoFormat.parse("2010-05-23T09:01:02");
isoFormat.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDateUtc = isoFormat.format(date);
System.out.println(strDateUtc);
isoFormat.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String strDateNewYork = isoFormat.format(date);
System.out.println(strDateNewYork);
}
}
Output:
2010-05-23T09:01:02
2010-05-23T05:01:02
ONLINE DEMO
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:
The modern Date-Time API is based on ISO 8601 and does not require using a DateTimeFormatter object explicitly as long as the Date-Time string conforms to the ISO 8601 standards.
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.parse("2010-05-23T09:01:02");
ZonedDateTime zdtUtc = ldt.atZone(ZoneId.of("Etc/UTC"));
System.out.println(zdtUtc);
ZonedDateTime zdtNewYork = zdtUtc.withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println(zdtNewYork);
}
}
Output:
2010-05-23T09:01:02Z[Etc/UTC]
2010-05-23T05:01:02-04:00[America/New_York]
ONLINE DEMO
Note: For any reason, if you need to convert this object of ZonedDateTime to an object of java.util.Date, you can do so as follows:
Date date = Date.from(zdtUtc.toInstant());
or
Date date = Date.from(zdtNewYork.toInstant());
Learn more about the modern Date-Time API from Trail: Date Time.
* 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.
First thing Java doesn't support EDT abbreviation instead use "EST5EDT". If something is not found it falls EST5EDT.
You can check full list of available timezones
In SimpleDateFormatter if you are using parse() it means you trying to read "from" something. If you are using format() it means you are trying to write "to" something.
Conclusion, In the case of parse() timezone act as input format but in case of format() it acts as output format. The below program converts an EDT date to IST date. Probably using the comments in the below example you will understand what exactly is happening.
// EDT Formatter
SimpleDateFormat edtFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
edtFormat.setTimeZone(TimeZone.getTimeZone("EST5EDT"));
// IST Formatter
SimpleDateFormat istFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
istFormat.setTimeZone(TimeZone.getTimeZone("IST"));
// Convert EDT to IST
String edtDate = "2010-05-23T00:00:00";
Date date = edtFormat.parse(edtDate); //Parse from EDT to Local Timezone
String istDate = istFormat.format(date); //Parse from Local Timezone to IST
System.out.println("EDT: "+edtDate);
System.out.print("Local Date: ");
System.out.println(date);
System.out.println("IST: "+istDate);
I understand java's inital release of java.util.Date was very badly designed which created a lot of confusion that is why later they introduced java.time api whose name are way clear like LocalDate, ZonedDate etc.

Convert date string from ISO 8601 format to another

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
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?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
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

Java unparseable date

There is the following code:
Date st = new SimpleDateFormat("HH:mm").parse(date);
And I get the following exception "Unparseable date: "2000-01-01T01:00:00Z" (at offset 4)". How can I fix it?
tl;dr
Instant.parse( "2000-01-01T01:00:00Z" )
Wrong Parsing Pattern
You defined a formatting pattern that says you expect the input string to be hours and minutes. But your input string has much more, years, months, and so on.
java.time
As of Java 8 and later, the old java.util.Date/.Calendar and java.text.SimpleDateFormat have been supplanted by the new java.time package. Avoid the old classes whenever possible as they have proven to be confusing, troublesome, and flawed.
Your input string is using one of the standard date-time formats defined by ISO 8601. Fortunately, java.time uses that format by default.
String input = "2000-01-01T01:00:00Z" ;
Instant instant = Instant.parse( input ) ;
An Instant is a moment on the timeline basically in UTC. You may adjust the value to a particular time zone (a ZoneId), producing a ZonedDateTime object.
ZonedId zoneId = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ZonedDateTime.of( instant , zoneId ) ;
If you call toString on a ZonedDateTime, you will get a string like:
1999-12-31T20:00:00-05:00[America/Montreal]
The ZonedDateTime class extends the ISO 8601 format by appending the name of the time zone in brackets.
Date st = new SimpleDateFormat("HH:mm").parse(date.substring(11,16));
Use this format instead:
Date st = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(date);
SimpleDateFormat is very unforgiving. It expects you to pass a String that exactly matches the format string you initialized it with. If you pass "HH:mm" as its format string, it will not be able to handle any other format - it cannot handle a date with a year in it, etc. It will handle "3:56" (in which case you'll get Jan 1, 1970 at 03:56AM in your Date).
SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Date date = dtf.parse(date);
dtf = new SimpleDateFormat("HH:mm");
String dateStr = dtf.format(date);
Date finalDate = dtf.parse(date);
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX")
The date in the exception is an xml schema dateTime. Note that simply creating
SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
Will not work entirely as you might think because the Z indicates "UTC" timezone and the parser is by default initialized as local time.
Also note that the schema dateTime has a variable definition, it can (optionally) have millisecond precision (0 or more milliseconds) and the timezone (if something other than Z) is not compatible with the format of SimpleDateFormat.
In short: xml date times are tricky with the default libraries. I have written a custom solution for handling them in our environment but you could also look at the joda time library which I believe handles them well. Or you could wait for the next java version which will have a new date API.

Java, How to change GMT time to local time?

Server sends me time like this:
2012-06-08 17:00:00 +0100
I need to change it like HH:MM based on local time. For example this time is what time at Japan, India, US and etc.
How can I do this? Thanks
Option 1: using java.util.Date/Calendar:
First you need to parse the value to a Date, then reformat it in the format and time zone
you're interested in:
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z",
Locale.US);
Date date = inputFormat.parse(inputText);
// Potentially use the default locale. This will use the local time zone already.
SimpleDateFormat outputFormat = new SimpleDateFormat("HH:mm", Locale.US);
String outputText = outputFormat.format(date);
Option 2: using Joda Time
Joda Time is a much better date/time library for Java.
DateTimeFormatter inputFormatter = DateTimeFormat
.forPattern("yyyy-MM-dd HH:mm:ss Z")
.withLocale(Locale.US);
DateTime parsed = inputFormatter.parseDateTime(inputText);
DateTimeFormatter outputFormatter = DateTimeFormat
.forPattern("HH:mm")
.withLocale(Locale.US)
.withZone(DateTimeZone.getDefault());
String outputText = outputFormatter.print(parsed);
Note that you should only convert to/from string representations when you really need to. Otherwise, use the most appropriate type based on your usage - this is where Joda Time really shines.
Use JodaTime. It's far better and safer than Java's Date and Time API. There are a lot of methods that return a LocalTime object (HH:MM).
As an example, new DateTime(your date time).toLocalTime();
java.util.Date is always in UTC. What makes you think it's in local time? I suspect the problem is that you're displaying it via an instance of Calendar which uses the local timezone, or possibly using Date.toString() which also uses the local timezone.
If this isn't the problem, please post some sample code.
I would, however, recommend that you use Joda Time anyway, which offers a much clearer API.
The other Answers are correct but outdated. Use java.time classes instead.
tl;dr
ZonedDateTime zdt_Kolkata = OffsetDateTime.parse( "2012-06-08 17:00:00 +0100" , DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss Z" ) ).atZone( ZoneId.of( "Asia/Kolkata" ) );
Using java.time
Define a DateTimeFormatter formatting pattern to match your input String.
String input = "2012-06-08 17:00:00 +0100";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss Z" );
OffsetDateTime
Parse the String as an OffsetDateTime object that represents the +0100 in your input which means “one hour ahead of UTC”.
OffsetDateTime odt = OffsetDateTime.parse( input , f );
ZonedDateTime
Apply a ZoneId to produce a ZonedDateTime for any desired time zone. Specify a proper time zone name. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId zoneId_Kolkata = ZoneId.of( "Asia/Kolkata" ); // India
ZonedDateTime zdt_Kolkata = odt.atZone( zoneId_Kolkata );
…and another…
ZoneId zoneId_Montréal = ZoneId.of( "Asia/Montreal" ); // Québec Canada
ZonedDateTime zdt_Montréal = odt.atZone( zoneId_Montréal );
Instant
For UTC, extract an Instant object. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.
Instant instant = zdt_Montréal.toInstant();
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time.

How to convert a date String to a Date or Calendar object?

I have a String representation of a date that I need to create a Date or Calendar object from. I've looked through Date and Calendar APIs but haven't found anything that can do this other than creating my own ugly parse method. I know there must be a way, does anyone know of a solution?
In brief:
DateFormat formatter = new SimpleDateFormat("MM/dd/yy");
try {
Date date = formatter.parse("01/29/02");
} catch (ParseException e) {
e.printStackTrace();
}
See SimpleDateFormat javadoc for more.
And to turn it into a Calendar, do:
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
tl;dr
LocalDate.parse( "2015-01-02" )
java.time
Java 8 and later has a new java.time framework that makes these other answers outmoded. This framework is inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project. See the Tutorial.
The old bundled classes, java.util.Date/.Calendar, are notoriously troublesome and confusing. Avoid them.
LocalDate
Like Joda-Time, java.time has a class LocalDate to represent a date-only value without time-of-day and without time zone.
ISO 8601
If your input string is in the standard ISO 8601 format of yyyy-MM-dd, you can ask that class to directly parse the string with no need to specify a formatter.
The ISO 8601 formats are used by default in java.time, for both parsing and generating string representations of date-time values.
LocalDate localDate = LocalDate.parse( "2015-01-02" );
Formatter
If you have a different format, specify a formatter from the java.time.format package. You can either specify your own formatting pattern or let java.time automatically localize as appropriate to a Locale specifying a human language for translation and cultural norms for deciding issues such as period versus comma.
Formatting pattern
Read the DateTimeFormatter class doc for details on the codes used in the format pattern. They vary a bit from the old outmoded java.text.SimpleDateFormat class patterns.
Note how the second argument to the parse method is a method reference, syntax added to Java 8 and later.
String input = "January 2, 2015";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "MMMM d, yyyy" , Locale.US );
LocalDate localDate = LocalDate.parse ( input , formatter );
Dump to console.
System.out.println ( "localDate: " + localDate );
localDate: 2015-01-02
Localize automatically
Or rather than specify a formatting pattern, let java.time localize for you. Call DateTimeFormatter.ofLocalizedDate, and be sure to specify the desired/expected Locale rather than rely on the JVM’s current default which can change at any moment during runtime(!).
String input = "January 2, 2015";
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate ( FormatStyle.LONG );
formatter = formatter.withLocale ( Locale.US );
LocalDate localDate = LocalDate.parse ( input , formatter );
Dump to console.
System.out.println ( "input: " + input + " | localDate: " + localDate );
input: January 2, 2015 | localDate: 2015-01-02
The highly regarded Joda Time library is also worth a look. This is basis for the new date and time api that is pencilled in for Java 7. The design is neat, intuitive, well documented and avoids a lot of the clumsiness of the original java.util.Date / java.util.Calendar classes.
Joda's DateFormatter can parse a String to a Joda DateTime.
Try this:
DateFormat.parse(String)
The DateFormat class has a parse method.
See DateFormat for more information.

Categories

Resources