Java unparseable date - java

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.

Related

Java, converting Calendar format to Date(YYYY-MM-DD)

Calendar calendar1 = Calendar.getInstance();
calendar1.setTime(LeaveDate);
calendar1.add(Calendar.DAY_OF_MONTH, ProcessDate);
Date fullDate1 = calendar1.getTime();
SimpleDateFormat date1 = new SimpleDateFormat("yyyy-MM-dd");
Here the output i.e., date1 is string, how to convert it to Date
tl;dr
Reading your code, apparently you want to take the current moment as seen in the current default time zone, adjust to a particular day of month, and then convert to a moment as seen in UTC to be represented by the outmoded class java.util.Date.
java.util.Date // Legacy class. Replaced by `java.time.Instant`.
.from( // New conversion method added to old class, to move between legacy and modern classes.
ZonedDateTime // Represents a moment as seen in a particular time zone.
.now() // Implicitly applies the JVM’s current default time zone.
.withDayOfMonth( yourDesiredDayOfMonthGoesHere ) // Adjust to another moment on another date. Returns another `ZonedDateTime` object immutably, rather than altering original.
.toInstant() // Adjust from time zone to UTC. Same moment, different wall-clock time.
) // Returns an object for the same moment, but as a legacy `Date` object. Avoid using this class if at all possible.
But your title asks for something different. The title asks how to generate text in a ISO 8601 standard format (YYYY-MM-DD) for a Calendar object. Assuming your Calendar object is a GregorianCalendar object, we can cast. Then we can convert to the modern java.time.ZonedDateTime object, extract the date-only java.time.LocalDate object, and generate standard text. The java.time classes use ISO 8601 formats by default when parsing/generating text, so no need for a formatting pattern.
(GregorianCalendar) yourCalendarHere // Cast from the more general `Calendar` to the more specific `GregorianCalendar`.
.toZonedDateTime() // Convert from legacy class to modern. Same moment in the same time zone. Returns a `java.time.ZonedDateTime` object.
.toLocalDate() // Strip away the time zone and the time-of-day, leaving only the date. Returns a `java.time.LocalDate` object.
.toString() // Generate text representing the value of that date in standard ISO 8601 format, YYYY-MM-DD. Returns a `String` object.
Tip: Stop using the terribly flawed legacy date-time classes. Use only java.time.
Formatters
Here the output i.e., date1 is string, how to convert it to Date
You seem to misunderstand the classes involved.
Your date1 is a variable declared to be a SimpleDateFormat object. That class is a formatter. As a formatter, its job is to generate text, not hold text nor hold a date. So your variable is misnamed, as it does not hold a date.
Avoid legacy classes
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310. Never use Date, Calendar, SimpleDateFormat, and such.
java.time
Replace this:
Calendar calendar1 = Calendar.getInstance();
… with this:
ZonedDateTime zdt = ZonedDateTime.now() ; // Implicitly uses the JVM’s current default time zone.
I assume that in this code:
calendar1.setTime(LeaveDate);
… the LeaveDate (should have been named with initial lowercase, leaveDate) represents a java.util.Date object. And you are trying to get a calendar object set to the moment represented by that Date object.
In java.time, we use immutable objects. So, no use of set methods. In java.time, if handed a java.util.Date object, immediately convert to an Instant. Both classes represent a moment as seen in UTC, with an offset of zero hours-minutes-seconds. To convert, use the new conversion methods added to the old classes.
Instant instant = leaveDate.toInstant() ;
Adjust that moment into a time zone.
ZoneId z = ZoneId.systemDefault() ; // The JVM’s current default time zone.
ZonedDateTime zdt = instant.atZone( z ) ;
Both instant & zdt represent the same moment, the very same point on the timeline. But their date and time-of-day are adjusted for the wall-clock time used by the people of two different regions. If someone in Iceland, where they use UTC as their time zone, called someone in Tokyo, and both people looked up to see the calendar and clock on their respective walls, they would see a different time and possibly a different date.
In your line:
calendar1.add(Calendar.DAY_OF_MONTH, ProcessDate);
… I am guessing that you want to set the day-of-month while keeping the same month, year, and time-of-day. For example, let's use the 23rd. Notice that we generate a new ZonedDateTime rather than alter ("mutate") the original. Adjustments are made automatically if the result would be impossible, such as the 30th of February.
ZonedDateTime zdtForSpecificDayOfMonth = zdt.withDayOfMonth( 23 ) ; // Change day-of-month to the 23rd.
Regarding your line:
Date fullDate1 = calendar1.getTime();
… as I said above, you should avoid using Date in modern Java. But if you must do so to interoperate with old code not yet updated to java.time, extract an Instant from the ZonedDateTime object, and convert to a java.util.Date.
Instant instant = zdtForSpecificDayOfMonth.toInstant() ; // Adjust from a time zone to an offset of zero hours-minutes-seconds.
java.util.Date d = Date.from( instant ) ;
Parsing dates in Java with DateFormat or descendants
Tested with Java's REPL jshell
jshell> import java.text.SimpleDateFormat;
jshell> var df = new SimpleDateFormat("yyyy-MM-dd");
df ==> java.text.SimpleDateFormat#f67a0200
jshell> Date dt = df.parse("2022-02-15");
dt ==> Tue Feb 15 00:00:00 CET 2022
Read the official JavaDoc for class SimpleDateFormat to figure out how to use it to parse a String to Date:
import java.text.SimpleDateFormat;
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date dt = df.parse("2022-02-15");
System.out.println(dt); // prints Tue Feb 15 00:00:00 CET 2022
Explained:
The "yyyy-MM-dd" as argument to the constructor is a date-format literal (representing ISO-date format).
The parse method parses a String with this format and returns the Date object if valid format, or throws a ParseException.
Or search Stackoverflow for [java] String to Date to find similar questions.
Formatting dates in Java with DateFormat or descendants
The other way round you can also format a Date object to have a well-formatted String representation. Use the format method of your DateFormat instance:
import java.text.SimpleDateFormat;
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date dt = df.parse("2022-02-15");
String formatted = df.format(dt);
System.out.println(formatted);
For example to format your Calendar instance use:
Calendar calendar1 = Calendar.getInstance();
// whatever modifies the calendar left out here
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String formatted = df.format(dt);
System.out.println(calendar1.getTime());

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.

Determine TimeZone from a JSON String?

I'm querying a JSON API that returns something like this:
{
"created_time": "2017-01-05T16:32:29+0100",
"updated_time": "2017-01-11T09:38:41+0100",
"id": "23842536731240607"
}
I need to store the times in UTC format, but in order to change the timezone, I first need to parse it as a ZonedDateTime.
To convert "+0100" to "+01:00" is easy enough. But how can I parse the (created/updated)_time into a ZonedDateTime so I can convert it to UTC?
There are some options.
First, as you say, inserting a colon in zone offset is not that difficult. After you’ve done that, getting a ZonedDateTime is straightforward:
ZonedDateTime zdt = ZonedDateTime.parse("2017-01-11T09:38:41+01:00");
System.out.println(zdt);
This prints:
2017-01-11T09:38:41+01:00
Alternatively, funnily, while ZonedDateTime.parse(String) needs a colon in the offset, ZoneId.of() does not, so you may split off the offset and do:
ZoneId zi = ZoneId.of("+0100");
LocalDateTime ldt = LocalDateTime.parse("2017-01-11T09:38:41");
ZonedDateTime zdt = ldt.atZone(zi);
The result is the same as before.
If you prefer not to modify your string prior to parsing it, there is also:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
ZonedDateTime zdt = ZonedDateTime.parse("2017-01-11T09:38:41+0100", dtf);
Also this gives the same result.
Edit: Note: I am using ZonedDateTime since you asked for this in your question. You may consider it more correct to use OffsetDateTime. Most of the code is practically the same. The version that splits off the offset would go like this:
ZoneOffset zo = ZoneOffset.of("+0100");
LocalDateTime ldt = LocalDateTime.parse("2017-01-11T09:38:41");
OffsetDateTime odt = ldt.atOffset(zo);
To convert to UTC, as mentioned at end of Question, apply another ZoneOffset, the constant ZoneOffset.UTC.
OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC );
Well let me break down the problem statement.
First if you are querying an API then it can be assumed that they are following some standard Date-Time format (even if you are creating one). Looking over the given date it looks like they follow - ** ISO 8601 - Date and time format **
So the problem is how to parse ISO 8601 - Date and time format
What are best options available ?
Using Joda Time.
Using Date Time API Java-8
//Joda
String jtDate = "2010-01-01T12:00:00+01:00";
DateTimeFormatter yoda = ISODateTimeFormat.dateTimeNoMillis();
System.out.println(parser2.parseDateTime(jtDate));
//using Java 8 (As you specified - To convert "+0100" to "+01:00" is easy enough.)
String strDate = "2017-01-05T16:32:29+01:00";
DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME;
TemporalAccessor convertMe = timeFormatter.parse(strDate);
Date date = Date.from(Instant.from(convertMe));
System.out.println(date);
Hope it helps :)

is there a simple way to convert Date(sql) to following format Month(3 character) day(int) , year(2014)

is there a simple way to convert Date(sql) to following format Month(3 character) day(int) , year(int)?
For example:
Jan 3, 2014
Feb 2, 2014
I have this: "2014-02-14"
(i use postgresql, java and javascript on client)
Assuming , if you want to achieve this in the Database side itself. Then use the below sql query.
Lets say "stack" is the column containing your DATE value ie "2014-02-14"
select to_char(stack,'Mon dd, YYYY') from testing;
to_char
--
Feb 14, 2014
Take a look at Java's SimpleDateFormat API
You can do something like this --
SimpleDateFormat format = new SimpleDateFormat("MMM dd, YYYY");
String dateString = format.format(date); // Pass your SQL date object here
This will work:
SimpleDateFormat format = new SimpleDateFormat("MMM dd, yyyy");
SimpleDateFormat sqlformat = new SimpleDateFormat("yyyy-mm-dd");
java.util.Date date;
try {
date = sqlformat.parse("2014-02-14");
String result = format.format(date);
System.out.println(result);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // Pass your SQL date object here
Short Answer
In Joda-Time 2.3 (substitute your desired time zone and Locale)…
String output = DateTimeFormat.forStyle( "M-" ).withLocale( new java.util.Locale( "fr", "CA" ).withTimeZone( "America/Montreal").print( new DateTime( myJavaDotSqlDotJavaObject ) );
A Date-Time Object Has No Format
You are making the common mistake of conflating a date-time value with its string representation. A java.sql.Date object has no String format. You can generate a String representation from a date-time object, but the two are separate independent objects.
ISO 8601
The format you mentioned is defined by the ISO 8601 standard. The Joda-Time date-time library uses ISO 8601 for its defaults for both inputs and outputs.
Time Zone
Both the question and other answers ignore the crucial issue of time zone.
Determining what day it is (yesterday, today, tomorrow) depends on your time zone. While a new day dawns in Paris for Feb 2, in Montréal the date is still Feb 1.
A java.sql.Date instance has no time zone. It's date-time value internally is effectively in UTC (no offset).
Decent Date-Time Library
The bundled java.util.Date and .Calendar classes in Java are notoriously troublesome. Avoid them. Use either:
Joda-Time
The new java.time package in Java 8.
Joda-Time
Some example code in Joda-Time 2.3.
Get the current date-time.
DateTimeZone timeZoneParis = DateTimeZone.forID( "Europe/Paris" );
DateTime nowInParis = DateTime.now( timeZone );
To convert your java.sql.Date instance to a Joda-Time object, simply pass it to the constructor. Be sure to include a time zone to be assigned to the Joda-Time DateTime object. If you omit the time zone, the JVM’s default zone is assigned.
DateTime dateTimeInParis = new DateTime( myJavaDotSqlDotDateObject, timeZoneParis );
Adjust for time zone.
DateTimeZone timeZoneMontréal = DateTimeZone.forID( "America/Montreal" );
DateTime nowInMontréal = nowInParis.withTimeZone( timeZone );
You may adjust to UTC. This might be helpful for debugging, to verify the UTC value stored in your database. Postgres always stores TIMESTAMP types in UTC. I repeat: both TIMESTAMP WITH TIME ZONE and TIMESTAMP WITHOUT TIME ZONE types are stored in UTC. The 'with' or 'without' names are misleading, as they refer not to storage but to whether or not a time zone is respected during insertion into or retrieval from the database. Expert advice says: Always use TIMESTAMP WITH TIME ZONE.
DateTime dateTimeInUtc = nowInMontréal.withTimeZone( DateTimeZone.UTC );
Generate a string representation of the date-time value using one of the built-in ISO 8601 formatters. For the date-only YYYY-MM-DD format you mentioned, call the factory method ISODateTimeFormat.date().
For the MMM DD, YYYY format you want, I suggest you instead use a localized format. See the line of code at the top of this answer for an example. Pass "M-" to generate a medium-length string representation of the date portion while omitting the time portion. Pass "F", "L", "M", or "S" for Full, Long, Medium, and Short.
If you insist on exactly your specified format, you may create a formatter using the DateTimeFormat.forPattern method. Search StackOverflow for many examples.
Note that the formatter can do the time zone adjusting as part of its process, as an alternative to the time zone adjustment we saw above. The formatter can also localize.
DateTimeFormat formatter = ISODateTimeFormat.date().withTimeZone( timeZoneMontréal ).withLocale( new java.util.Locale( "fr", "CA" ); // Factory producing formatters.
String outputDateOnlyInMontréal = formatter.print( nowInParis );

Parse Date String to Some Java Object

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

Categories

Resources