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
Related
I have a string containing a date in the form
04-Jan-15
and need to get the week number of the year out of it.
for the above example week 1(or 2 depending on locale and weekdays in December. never mind that).
I have this:
String[] startDate=dates[0].split("-");
int month,day,year;
year=2000+Integer.parseInt(startDate[2]);
day=Integer.parseInt(startDate[0]);
switch (startDate[1]){
case "Jan":
{
month=1;
break;
}
........
........
case "Dec":
{
month=12;
break;
}
}
Calendar temp=new GregorianCalendar();
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
try {
Date tempDate = sdf.parse(day+"/"+month+"/"+year);
System.out.println("DATE:"+tempDate);
temp.setTime(tempDate);
System.out.println("Calendar Month:"+temp.MONTH);
System.out.println("Calendar Week:"+temp.WEEK_OF_YEAR);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
This returns
DATE:Sun Jan 04 00:00:00 EET 2015
Calendar Month:2
Calendar Week:3
I tried (earlier) this
temp.set(year, month, day);
and was still getting wrong results.
Any idea?
tl;dr
For culturally-defined weeks…
LocalDate.parse(
"04-Jan-15" ,
DateTimeFormatter.ofPattern( "dd-MMM-uu" , Locale.US )
).get(
WeekFields.of( Locale.FRANCE ).weekOfWeekBasedYear( )
) // Gets week number for a culturally-defined week-of-year.
For standard weeks…
LocalDate.parse(
"04-Jan-15" ,
DateTimeFormatter.ofPattern( "dd-MMM-uu" , Locale.US )
).get(
IsoFields.WEEK_OF_WEEK_BASED_YEAR
) // Gets standard ISO 8601 week number.
java.time
You are using troublesome old date-time classes that are now legacy, supplanted entirely by the java.time classes. Much simpler now to solve your problem.
Parse your input string. Specify a Locale to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.
String input = "04-Jan-15";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MMM-uu" , Locale.US );
LocalDate ld = LocalDate.parse( input , f );
Dump to console.
System.out.println( "input: " + input + " = " + ld );
input: 04-Jan-15 = 2015-01-04
Week number
Week number is culturally defined. To access week-of-year, you must specify a Locale whose culture you want to use in defining a week.
Locale locale = Locale.FRANCE;
WeekFields fields = WeekFields.of( locale );
TemporalField field = fields.weekOfWeekBasedYear( );
int weekNumber = ld.get( WeekFields.of( Locale.FRANCE ).weekOfWeekBasedYear( ) ); // Gets week number for a culturally-defined week-of-year.
ISO 8601 defines standard week numbers where week # 1 contains the first Thursday of the year, and begins on a Monday. The java.time class offer this approach built-in in the IsoFields class.
int weekNumber = ld.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) // Gets standard ISO 8601 week number.
ISO 8601
By the way, that input string format is not good. When exchanging date-time values as text, always use ISO 8601 standard formats. These are used by default in java.time when parsing/generating strings.
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.
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
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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.
MONTH and WEEK_OF_YEAR in class Calendar are constants, not the month and week of year of any particular Calendar object.
You use these constants with the get(...) method. The constant indicates which field you want to get. Like this:
System.out.println("Calendar Month:" + temp.get(Calendar.MONTH));
System.out.println("Calendar Week:" + temp.get(Calendar.WEEK_OF_YEAR));
Also, there's a much easier way to parse a string like 04-Jan-15 into a Date object than doing it manually:
String text = "04-Jan-15";
DateFormat df = new SimpleDateFormat("dd-MMM-yy", Locale.US);
Date date = df.parse(text);
(Why are you first parsing the string manually, then converting it into another format dd/MM/yyyy and then parsing that again? That's much more complicated than necessary).
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
I am trying to parse an SQL date string (ISO 9075) and that uses microseconds(!) instead of milliseconds, for example
2010-11-22 08:08:08.123456
However, SimpleDateFormat refuses to recognize a pattern like "yyyy-MM-dd HH:mm:ss.SSSSSS" and "yyyy-MM-dd HH:mm:ss.SSS" does not work, either.
The code I am using looks something like this:
String dateString = "2010-11-22 08:08:08.123456";
String pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS";
try
{
format = new SimpleDateFormat(pattern);
format.setLenient(false);
position.setIndex(0);
Date date1 = format.parse(dateString, position);
System.out.println("Date 1: " + date1);
Date date2 = format.parse(dateString);
System.out.println("Date 2: " + date1);
}
catch (Exception e) // Should not happen
{
e.printStackTrace();
}
Whichever of the 2 patterns (".SSS" or ".SSSSSS") I use, date1 is printer as null, whereas date2 causes a parsing exception (java.text.ParseException: Unparseable date).
Maybe chop the remaining fraction part out of the dateString before parse the date? I have the following
String dateString = "2010-11-22 08:08:08.123456";
String fraction = dateString.substring(dateString.length() - 3);
String formatString = dateString.substring(0, dateString.length() - 3);
String pattern = "yyyy-MM-dd HH:mm:ss.SSS";
ParsePosition position = new ParsePosition(0);
try
{
SimpleDateFormat format = new SimpleDateFormat(pattern);
format.setLenient(false);
position.setIndex(0);
Date date1 = format.parse(formatString, position);
System.out.println("Date 1: " + date1);
System.out.println("Date 1 fraction: " + fraction);
Date date2 = format.parse(formatString);
System.out.println("Date 2: " + date2);
System.out.println("Date 2 fraction: " + fraction);
}
catch (Exception e) // Should not happen
{
e.printStackTrace();
}
This allow the date to parse until millisecond precision while you still retain the fraction micro part.
Hmm. Given that Date doesn't have microsecond resolution, if you know that all the SQL date strings have the full six digits after the seconds decimal point (2010-11-22 08:08:08.000000 for example), why not just chop off the final three digits and use SimpleDateFormat on the remainder?
You may want to look at DATE4J which specifically tries to deal with database dates, to nanosecond precision.
You might want to call the DateFormat parse, because I think it will cut off the string. Try:
Date date1 = format.parse(dateString);
Plus, don't use "SSSSS". According to specs, only "SSS" is valid for dateformat.
Other than that, I agree with cutting it off or parsing in SQL.
Plus, you have setLenient to false, so it's strict. So the string, being longer is going to cause it to fail. Maybe that's why it returns null. Unsure, would have to test.
tl;dr
Insert/Update.
myPreparedStatement.setObject(
… ,
Instant.parse( "2010-11-22 08:08:08.123456".replace( " " , "T" ) + "Z" )
) ;
Retrieval.
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
String output = ldt.toString().replace( "T" , " " ) ; // Remove the standard ISO 8601 format’s use of `T` in the middle with the SQL-style SPACE.
java.time
Java 8 brings the new java.time package, to supplant the notoriously troublesome old java.util.Date, .Calendar, and SimpleDateFormat classes. Those old legacy classes are limited to milliseconds resolution while your input string has microseconds. You cannot cram six decimal places into a data type limited to three.
The date-time values in java.time have nanosecond resolution, more than enough for your microseconds. That means up to nine decimal places for a fractional second.
With JDBC 4.2 and later, use the Instant class directly.
Parse your input String. To comply with ISO 8601 format used by default in the java.time classes, replace the SPACE in the middle with a T. Your given example must be coming from a column type TIMESTAMP WITHOUT TIME ZONE which means not a specific moment, not a point on the timeline.
String input = "2010-11-22 08:08:08.123456".replace( " " , "T" ) ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
And if this input was meant to be a moment in UTC, append a Z. Then you do have a moment, a specific point on the timeline. For use with a column type of TIMESTAMP WITH TIME ZONE.
String input = "2010-11-22 08:08:08.123456".replace( " " , "T" ) + "Z" ;
Instant instant = Instant.parse( input ) ;
Send to your database.
myPreparedStatement.setObject( … , instant ) ;
…and…
Instant instant = myResultSet.getObject( … , Instant.class ) ;
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, 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.
UPDATE: The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. Leaving this section intact as history.
Joda-Time
As noted above, you should avoid using the java.util.Date, .Calendar, and SimpleDateFormat classes. As of Java 8 you have the choice of using java.time or Joda-Time or both, as they each their strengths and weaknesses. Joda-Time also works in earlier versions of Java.
You can parse that string using Joda-Time.
Alternatively, if you have access to the java.sql.Timestamp that generated your string, you can simply pass the Timestamp object to the constructor of a DateTime. I suggest also passing a time zone as DateTime objects know their own assigned time zone.
DateTime dateTime = new DateTime( mySqlTimestamp, DateTimeZone.UTC );
or
DateTime dateTime = new DateTime( mySqlTimestamp, DateTimeZone.forID( "Europe/Paris" ) );
Joda-Time has a resolution of milliseconds. So either way you generate the DateTime (parsing or passing), you will loose the finer fraction of the second (ignored/truncated, not rounded).
If you have control over the SQL date which is an input to the java code, you could try and retrieve the date from SQL in a format which will work ("yyyy-MM-dd HH:mm:ss.SSS").
I get the following error:
´java.text.ParseException: Unparseable date: "Aug 31 09:53:19 2011"´ with this format: new SimpleDateFormat("MMM dd HH:mm:ss yyyy");
Does anyone see the problem?
Make sure you're using the correct locale. (The SimpleDateFormat(String) constructor uses the system default locale, which may not be the one you want to use.)
This works fine on my machine:
String input = "Aug 31 09:53:19 2011";
DateFormat df = new SimpleDateFormat("MMM dd HH:mm:ss yyyy", Locale.US);
System.out.println(df.parseObject(input));
(While using Locale.FRENCH for instance, results in a ParseException.)
The format itself is OK for the input you gave. But you might get this error if your default locale is set to something where "Aug" is not a valid abbreviation of a month name. Try using for example to Locale.US and you'll see that it will work:
DateFormat df = new SimpleDateFormat("MMM dd HH:mm:ss yyyy", Locale.US);
Date date = df.parse("Aug 31 09:53:19 2011");
tl;dr
Specify the Locale, to determine human language and cultural norms used in translating the name of month.
Use modern java.time classes rather that troublesome legacy classes.
Contrived example:
LocalDateTime.parse( // Parse input text as a `LocalDateTime` lacking any concept of time zone or offset-from-UTC.
"Aug 31 09:53:19 2011" ,
DateTimeFormatter.ofPattern( "MMM dd HH:mm:ss yyyy" ) // Specify formatting pattern to match input string.
.withLocale( Locale.US ) // The `Locale` determines the human language and cultural norms used in translating the input text.
) // Returns a `LocalDateTime` object.
Details
The other two answers by aioobe and by Jesper are both correct: Implicitly using a Locale with a human language that does not match the language of your input text.
This Answer explains a new way of doing the job. Also, the other Answers do not address the crucial issue of time zone.
java.time
Fast forward a few years later from this posting, and we now have the new java.time package built into Java 8 and later. These new classes supplant the old java.util.Date/.Calendar & SimpleDateFormat classes. Those old classes have proven to be troublesome, confusing, and flawed.
Formatter Pattern
Define the data to be parsed and its format.
String input = "Aug 31 09:53:19 2011";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MMM dd HH:mm:ss uuuu" );
If not specified, the DateTimeFormatter is assigned the Locale that is currently the default in the JVM. That default can change at any moment, even during runtime(!). So always specify the desired/expected Locale.
formatter = formatter.withLocale( Locale.US ); // Or Locale.UK, Locale.CANADA_FRENCH, etc.
Given that the input lacks any time zone or offset-from-UTC information, parse as a LocalDateTime.
LocalDateTime ldt = LocalDateTime.parse( input , formatter );
If from the context you know the intended offset-from-UTC or a time zone for this date-time value, assign it.
If UTC, use the ZoneOffset.UTC constant to get a OffsetDateTime object.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
A time zone is an offset-from-UTC plus a set of rules for handling anomalies such as Daylight Saving Time (DST). Use proper time zone names, never the 3-4 letter abbreviations.
ZoneId zoneId_Montreal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId_Montreal );
Specify Time Zone
This human language element was the key missing piece to answer the Question. Specifying the correct Locale for the human language matching the language of your input string solves that problem.
But note that the time zone is also critical; the other answers ignored this issue thereby implicitly using the JVM’s current default time zone. That is not advisable, as it depends on the host operating system as an initial default value (so may vary) and furthermore any code in any thread of any app within the JVM can change the JVM’s current default time zone during runtime. Better to specify the desired/expected time zone than rely implicitly on default.
Immutable Objects
Note the syntax. These classes are designed to be immutable. So rather than modifying (mutating) an object, a fresh new object is created based on the old object’s values. This means we are not affecting the DateTimeFormatter object defined above and held in the formatter variable (object reference). We are creating, using, and discarding a new DateTimeFormatter object (actually, two new objects) within this line of code.
Method Reference
The documentation suggests an alternative way to parse a string is to call the parse method where you pass a method reference (new in Java 8) from the class of the kind of result you desire (as the TemporalQuery): ZonedDateTime::from, LocalDateTime::from, LocalDate::from, and so on.
ZonedDateTime zdt = formatter.withZone( zoneId_Montreal ).withLocale( Locale.ENGLISH ).parse( input, ZonedDateTime :: from );
For demonstration, let's turn around and create a String representation of that ZonedDateTime value but in Québécois French.
String output = formatter.withLocale( Locale.CANADA_FRENCH ).format( zdt );
Even better, let’s localize rather than hard-code a particular format.
String outputLocalized = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ).format( zdt );
Dump to console.
System.out.println( "input: " + input );
System.out.println( "formatter: " + formatter );
System.out.println( "zdt: " + zdt );
System.out.println( "output: " + output );
System.out.println( "outputLocalized: " + outputLocalized );
When run.
input: Aug 31 09:53:19 2011
formatter: Text(MonthOfYear,SHORT)' 'Value(DayOfMonth,2)' 'Value(HourOfDay,2)':'Value(MinuteOfHour,2)':'Value(SecondOfMinute,2)' 'Value(YearOfEra,4,19,EXCEEDS_PAD)
zdt: 2011-08-31T09:53:19-04:00[America/Montreal]
output: août 31 09:53:19 2011
outputLocalized: mercredi 31 août 2011 9 h 53 EDT
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, Java SE 10, 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….
I have a string in the pattern yyyy-MM-dd hh:mm a
and i can get the time zone object separately in which the above string represents the date.
I want to convert this to the below format.
yyyy-MM-dd HH:mm:ss Z
How can i do this?
You can use SimpleDateFormat with yyyy-MM-dd HH:mm:ss and explicitly set the TimeZone:
public static Date getSomeDate(final String str, final TimeZone tz)
throws ParseException {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm a");
sdf.setTimeZone(tz);
return sdf.parse(str);
}
/**
* #param args
* #throws IOException
* #throws InterruptedException
* #throws ParseException
*/
public static void main(final String[] args) throws ParseException {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
System.out.println(sdf.format(getSomeDate(
"2010-11-17 01:12 pm", TimeZone.getTimeZone("Europe/Berlin"))));
System.out.println(sdf.format(getSomeDate(
"2010-11-17 01:12 pm", TimeZone.getTimeZone("America/Chicago"))));
}
Prints out:
2010-11-17 13:12:00 +0100
2010-11-17 20:12:00 +0100
Update 2010-12-01:
If you want to explicitly printout a special TimeZone, set it in the SimpleDateFormat:
sdf.setTimeZone(TimeZone .getTimeZone("IST"));
System.out.println(sdf.format(getSomeDate(
"2010-11-17 01:12 pm", TimeZone.getTimeZone("IST"))));
Which prints 2010-11-17 13:12:00 +0530
tl;dr
LocalDateTime.parse( // Parse string as value without time zone and without offset-from-UTC.
"2017-01-23 12:34 PM" ,
DateTimeFormatter.ofPattern( "uuuu-MM-dd hh:mm a" )
) // Returns a `LocalDateTime` object.
.atZone( ZoneId.of( "America/Montreal" ) ) // Assign time zone, to determine a moment. Returns a `ZonedDateTime` object.
.toInstant() // Adjusts from zone to UTC.
.toString() // Generate string: 2017-01-23T17:34:00Z
.replace( "T" , " " ) // Substitute SPACE for 'T' in middle.
.replace( "Z" , " Z" ) // Insert SPACE before 'Z'.
Avoid legacy date-time classes
The other Answers use the troublesome old date-time classes (Date, Calendar, etc.), now legacy, supplanted by the java.time classes.
LocalDateTime
I have a string in the pattern yyyy-MM-dd hh:mm a
Such an input string lacks any indication of offset-from-UTC or time zone. So we parse as a LocalDateTime.
Define a formatting pattern to match your input with a DateTimeFormatter object.
String input = "2017-01-23 12:34 PM" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd hh:mm a" );
LocalDateTime ldt = LocalDateTime.parse( input , f );
ldt.toString(): 2017-01-23T12:34
Note that a LocalDateTime is not a specific moment, only a vague idea about a range of possible moments. For example, a few minutes after midnight in Paris France is still “yesterday” in Montréal Canada. So without the context of a time zone such as Europe/Paris or America/Montreal, just saying “a few minutes after midnight” has no meaning.
ZoneId
and i can get the time zone object separately in which the above string represents the date.
A time zone is represented by the ZoneId class.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. 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 z = ZoneId.of( "America/Montreal" );
ZonedDateTime
Apply the ZoneId to get a ZonedDateTime which is indeed a point on the timeline, a specific moment in history.
ZonedDateTime zdt = ldt.atZone( z );
zdt.toString(): 2017-01-23T12:34-05:00[America/Montreal]
Instant
I want to convert this to the below format. yyyy-MM-dd HH:mm:ss Z
First, know that a Z literal character is short for Zulu and means UTC. In other words, an offset-from-UTC of zero hours, +00:00.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
You can extract a Instant object from a ZonedDateTime.
Instant instant = zdt.toInstant(); // Extracting the same moment but in UTC.
To generate a string in standard ISO 8601 format, such as 2017-01-22T18:21:13.354Z, call toString. The standard format has no spaces, uses a T to separate the year-month-date from the hour-minute-second, and appends the Z canonically for an offset of zero.
String output = instant.toString();
instant.toString(): 2017-01-23T17:34:00Z
I strongly suggest using the standard formats whenever possible. If you insist on using spaces as in your stated desired format, either define your own formatting pattern in a DateTimeFormatter object or just do a string manipulation on the output of Instant::toString.
String output = instant.toString()
.replace( "T" , " " ) // Substitute SPACE for T.
.replace( "Z" , " Z" ); // Insert SPACE before Z.
output: 2017-01-23 17:34:00 Z
Try this code live at IdeOne.com.
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.
Where to obtain the java.time classes?
Java SE 8 and 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 SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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.
Use SimpleDateFormat
String string1 = "2009-10-10 12:12:12 ";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z")
sdf.setTimeZone(tz);
Date date = sdf.parse(string1);
Create a new instance of SimpleDateFormat using your date pattern. Afterwards you can call it's parse method to convert date strings to a java.util.Date object.
Undoubtedly, the format which is generally used will be of a form 2014-10-05T15:23:01Z (TZ)
For that one has to use this code
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
String dateInString = "2014-10-05T15:23:01Z";
try {
Date date = formatter.parse(dateInString.replaceAll("Z$", "+0000"));
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
Its output will be Sun Oct 05 20:53:01 IST 2014
However, I am not sure why we had to replaceAll "Z" if you do not add replaceAll the program will fail.
Please try this for the format "yyyy-MM-dd HH:mm:ss Z",
Eg: "2020-12-11 22:59:59 GMT", you can use different time zones like PST, GMT, etc.