Java SimpleDateFormat transform into wrong Date - java

this is maybe a simple question. I am Using SimpleDateFormat to transform a String into a date. I searched through the internet to solve my problem, but i didn't find anything.
But the transformation is wrong. I don't know why.
I want to get the format for example 2015.09.30
This is the Code
Date date1 = null;
String sd ="2015.09.30";
try {
SimpleDateFormat sdToDate = new SimpleDateFormat("yyyy.MM.dd");
date1 = sdToDate.parse(sd);
} catch (ParseException ex2) {
ex2.printStackTrace();
}
When i know output date1, I get this:
Wed Sep 30 00:00:00 CEST 2015
I hope someone can help me. It's maybe a simple question but i don't get it.

When you print date1 as e.g.:
System.out.println(date1);
Java uses Date::toString() function - so you print date in default format.
If you want to print it in different you need to use formatter, e.g.:
System.out.println(sdToDate.format(date1));

The Answer by Joanna Kotuła is correct, but uses old classes. We now have a better alternative.
java.time
You are using outmoded classes. In Java 8 and later use the java.time framework. See Tutorial.
The new classes include a class for date-only values, without time-of-day nor time zone: LocalDate.
Standard Format
Your input strings are in a format close to that used by the ISO 8601 standard, but the standard uses a HYPHEN rather than a FULL STOP, year-month-day. The standard formats are used java.time classes by default for parsing and generating textual representations of date-time values. So if I were you I would simply replace the characters, and avoid bothering to define a custom parsing format.
String input = "2015.09.30".replace( "." , "-" );
LocalDate localDate = LocalDate.parse( input );
Custom Format
The toString method on LocalDate automatically uses the standard ISO 8601 format of uuuu-MM-dd.
If you want to generate output strings in your own format, you will need to define a custom format pattern. Use the java.time.format package.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "uuuu.MM.dd" );
String output = localDate.format( formatter );
You can also parse with that formatter.
LocalDate localDate = LocalDate.parse( "2015.09.30" , formatter );

Related

SimpleDateFormat doesn't give me the pattern I need

I'm having a problem with SimpleDateFormat. I have inputfields in my HTML-page with type = date. I want to save these values into my database where they should be saved as dates. I already figured out how to do this and it works. The only probem I encouter is the way the dates are represented in the database.
I want them to be representated as dd-MM-yyyy. Let's say I want to display 01-06-2016 into my database. When doing this with the code I have..it gives me 0006-12-07. Strangely..when I change my pattern into yyyy-MM-dd...it does give me exactly what the pattern says: 2016-06-01. But it doesn't work the other way round.
String parameter = request.getParameter("instroomdatum");
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
Date parsed = sdf.parse(parameter);
java.sql.Date sql = new java.sql.Date(parsed.getTime());
student.setInstroomdatum(sql);
} catch (ParseException ex) {
Logger.getLogger(StudentController.class.getName()).log(Level.SEVERE, null, ex);
}
Can somebody please explain me what's going on and how to fix this problem? It's really annoying.
EDIT: I tried printing the value of parameter with a simple PrintWriter-object for the specific date 01-06-2016. It shows me 2016-06-01, even though my pattern in the code above is set to dd-MM-yyyy.
You are confusing the display format with the internal representation.
Dates in a database are not represented in any specific display format, such as YYYY-MM-DD. Database dates are normally stored in a numeric form that represents a certain number of seconds and milliseconds (or nanoseconds) from some fixed starting point.
The display format is applied dynamically when you query the database and ask for the date/time as a string, but if you ask for it as a Date object, you get the internal representation, encapsulated in a java.sql.Date.
It is up to your Java code to format the date as you need it.
In your particular example (according to your comment), the string returned by your input method is 2016-06-01, so you need to parse it with the pattern yyyy-MM-dd. This will correctly convert the external representation to a valid Date object.
But how should i specifically change this representation to dd-MM-yyyy
Once you have it as Date, you can immediately turn around and convert the Date back into a String with a different SimpleDateFormat specification.
Date-Time != String
As explained in the correct Answer by Garrison, you must understand that a date’s value internally in a database or in a language such as Java is distinct is distinct from a String generated to represent or communicate that value.
How the date is internally tracked varies amongst databases and languages, and is irrelevant really. What matters is the interface provided by which you can fetch or put your app’s values. A separate issue is how to represent those values as Strings for presentation to your user.
Database (internal) ↔ Driver (JDBC) ↔ App (java.time) ↔ Presentation (String)
java.time
Also, the Question and the other Answers are using old outmoded classes, the date-time classes bundled with the earliest versions of Java. Those classes have been supplanted by the java.time classes built into Java 8 and later. See Oracle Tutorial. Much of the functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
LocalDate
Amongst the java.time classes is LocalDate to represent a date-only value without time-of-day and without time zone. The old java.util.Date class, despite its unfortunate name, tracks both a date and a time-of-day. The old java.sql.Date pretends to represent a date-only but in fact, in an unfortunate design decision, extends from java.util.Date so it inherits both a date and a time-of-day, but you are instructed in the class doc to pretend that it is not a subclass. (yes, that is an unpleasant mess)
Do all your business logic using the java.time classes such as LocalDate.
Strings & ISO 8601
As for strings, use the standard ISO 8601 formats. For serializing date-only values, that means YYYY-MM-DD. The java.time classes use ISO 8601 formats by default when parsing/generating strings that represent date-time values.
LocalDate localDate = LocalDate.parse( "2016-06-01" );
But try to stick with objects. Serialize to strings only when you must.
Database
No need for strings when getting data to/from a database. The job of a JDBC driver is to figure out how to move a Java object to/from a data type of your database column.
With a driver that complies with JDBC 4.2, you should be able to use the getObject and setObject methods on a PreparedStatement to deal directly with java.time types.
myPreparedStatement.setObject( 1 , localDate );
If your driver does not support that, you must fall back onto the java.sql.Date class. Look for new methods added to the old classes to go back and forth with java.time types.
java.sql.Date sqlDate = java.sql.Date.valueOf( localDate );
And the other direction.
LocalDate localDate = sqlDate.toLocalDate();
Generate Strings
Apply a format to generate a string as needed for presentation to a user. Use the DateTimeFormatter class. You can define your own formatting pattern.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "dd-MM-yyyy" );
String output = localDate.format( formatter ); // 01-06-2016
Better yet, let java.time localize to the human language and cultural norms of the user’s desired/expected Locale.
Locale locale = Locale.CANADA_FRENCH;
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT , locale );
String output = localDate.format( formatter );
You will need to use the formatter to generate a String for presentation to the user, and to parse input made by the user. You or your users may wish instead to take data-entry as three separate fields: year, month, and day-of-month.
LocalDate localDate = LocalDate.of( 2016 , 6 , 1 );
If all you want to do is format your date into 01-06-2016 format. Try this
String parameter = "0006-12-07";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
Date parsed = sdf.parse(parameter);
sdf = new SimpleDateFormat("dd-MM-yyyy");
System.out.println(sdf.format(parsed)); //Prints out your desired format 07-12-0006
java.sql.Date sql = new java.sql.Date(parsed.getTime());
student.setInstroomdatum(sql);
} catch (ParseException ex) {
Logger.getLogger(StudentController.class.getName()).log(Level.SEVERE,null, ex);
}
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
java.sql.Date someDate;
Date anotherDate = format.parse(/*needVariables*/.getOutDate());
someDate = new java.sql.Date(anotherDate.getTime());
work for me

java.lang.IllegalArgumentException: Parse error: Unable to parse Date format

I need to format following date fomat
timeBooked: "2015-05-20T02:08:00.000Z",
ExpiryTime: "2015-05-20T04:08:00.000Z",
My code follows to format the date:
try {
Date currentDate = new Date(timeBooked);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.ZZ", Locale.ENGLISH);
Log.e(TAG, "formatted time string: " + sdf.format(currentDate.getTime()));
Log.e(TAG, "date string:=" + currentDate.getDate());
} catch (Exception e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
While running this code getting java.lang.IllegalArgumentException: Parse error:2015-05-20T02:08:00.000Z.
Your format String is incorrect. It should be "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'".
Then to get your date correctly you should use:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH);
// Set time zone to UTC since 'Z' at end of String specifies it.
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
// The parsed date will be offset from UTC in device's current TimeZone.
Date currentDate = sdf.parse(timeBooked);
The Date constructor taking a string is deprecated: see http://developer.android.com/reference/java/util/Date.html#Date(java.lang.String). It won't accept a custom date format; only a pre-defined set of formats are allowed.
Once you get your DateFormat string correct (I think "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" should work) you can call sdf.parse(timeBooked) to get a valid Date.
Z Has Meaning
Both of the previous Answers tell you to expect-and-ignore the Z character, by surrounding with single quotes in the coded parsing pattern. Bad advice. You would be ignoring valuable data, and would be rejecting valid alternative inputs such as 2015-05-20T02:08:00.000+05:30. The pattern code Z means "any valid offset-from-UTC". Adding the single quotes for 'Z' says "expect an uppercase Z to appear here, ignore any meaning it may have, and throw an exception if the Z is missing".
Joda-Time
You are using the old date-time classes bundled with early versions of Java. Those classes have proven to be troublesome, flawed in both design and implementation. Avoid them. In current Android, add the Joda-Time library to your project. In Java 8 and later, use the java.time framework that was inspired by Joda-Time.
Your string inputs are in ISO 8601 standard format. Both Joda-Time and java.time use ISO 8601 as their defaults when parsing/generating textual representations of date-time values. So you these classes can directly parse such strings without you needing to specify any coded parsing patterns.
The following code creates a date-time assigned an offset-from-UTC of 0, which is what the Z (for Zulu) means.
DateTime dateTime = DateTime.parse( "2015-05-20T02:08:00.000Z" );
Using a constructor has a different meaning. The following code parses the value with an offset of zero but then adjusts the results into your JVM’s current default time zone.
DateTime dateTime = new DateTime( "2015-05-20T02:08:00.000Z" ) );
I suggest you always explicitly assign your desired/expected time zone.
DateTimeZone zone = DateTimezone.forID( "Europe/Paris" );
DateTime dateTime_Europe_Paris = dateTime.withZone( zone );
If you really need a java.util.Date, convert after doing your parsing and business logic with Joda-Time.
java.util.Date date = dateTime.toDate();
Search StackOverflow for many more Questions and Answers with example code for Joda-Time.

Converting a time String to ISO 8601 format

I am trying to create a String in a format like 2015-08-20T08:26:21.000Z
to 2015-08-20T08:26:21Z
I know it can be done with some String splitting techniques, but i am wondering if there is an elegant solution for that (with minimal code changes).
Both of the above are time strings, the final one which i need is Date in ISO 8601 . https://www.rfc-editor.org/rfc/rfc3339#section-5.6
I have tried a few similar questions like converting a date string into milliseconds in java but they dont actually solve the purpose.
Also tried using :
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ");
String nowAsString = df.format(new Date());
But it still does not do any String to String conversions. Getting the following error:
23:04:13,829 WARN [RuntimeExceptionMapper] caught RuntimeException: {}: java.lang.IllegalArgumentException: Cannot format given Object as a Date
Is there some library which someone can suggest ?
Thanks.
tl;dr
Instant.parse( "2015-08-20T08:26:21.000Z" )
.toString()
2015-08-20T08:26:21Z
Date-Time Formatter
If all you want to do is eliminate the .000, then use date-time objects to parse your input string value, then generate a new string representation of that date-time value in a different format.
ISO 8601
By the way, if that is your goal, the Question’s title make no sense as both strings mentioned in the first sentence are valid ISO 8601 formatted strings.
2015-08-20T08:26:21.000Z
2015-08-20T08:26:21Z
java.time
Java 8 and later has the new java.time package. These new classes supplant the old java.util.Date/.Calendar & java.text.SimpleDateFormat classes. Those old classes were confusing, troublesome, and flawed.
Instant
If all you want is UTC time zone, then you can use the Instant class. This class represents a point along the timeline without regard to any particular time zone (basically UTC).
DateTimeFormatter.ISO_INSTANT
Calling an Instant’s toString generates a String representation of the date-time value using a DateTimeFormatter.ISO_INSTANT formatter instance. This formatter is automatically flexible about the fractional second. If the value has a whole second, no decimal places are generated (apparently what the Question wants). For a fractional second, digits appear in groups of 3, 6, or 9, as needed to represent the value up to nanosecond resolution. Note: this format may exceed ISO 8601 limit of milliseconds (3 decimal places).
Example code
Here is some example code in Java 8 Update 51.
String output = Instant.parse( "2015-08-20T08:26:21.000Z" ).toString( );
System.out.println("output: " + output );
output: 2015-08-20T08:26:21Z
Changing to a fractional second, .08
String output = Instant.parse( "2015-08-20T08:26:21.08Z" ).toString( );
output: 2015-08-20T08:26:21.080Z
If interested in any time zone other than UTC, then make a ZonedDateTime object from that Instant.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , ZoneId.of( "America/Montreal" ) ) ;
Your format is just not right try this :-
try {
String s = "2015-08-20T08:26:21.000Z";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
Date d = df.parse(s);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
System.out.println(sdf.format(d));
} catch (ParseException e) {
e.printStackTrace();
}
Conversion of a date String of unknown formatting into a date String that uses known formatting can be accomplished using two DateFormat objects- one dynamically configured to parse the format of the input String, and one configured to generate the formatted output String. For your situation the input String formatting is unspecified and must be provided by the caller, however, the output String formatting can be configured to use ISO 8601 formatting without additional input. Essentially, generating an ISO 8601 formatted date String output requires two inputs provided by the caller- a String containing the formatted date and another String that contains the SimpleDateFormat format.
Here is the described conversion as Java code (I deliberately have left out null checks and validations, add these as appropriate for your code):
private String formatDateAsIso8601(final String inputDateAsString, final String inputStringFormat) throws ParseException {
final DateFormat iso8601DateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.ENGLISH);
iso8601DateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
final DateFormat inputDateFormatter = new SimpleDateFormat(inputStringFormat, Locale.ENGLISH);
final Date inputDate = inputDateFormatter.parse(inputDateAsString);
return iso8601DateFormatter.format(inputDate);
}
If you want to modify that method please note that SimpleDateFormat is not thread-safe, and that you should not use it from a static context without a workaround for multi-threaded code (ThreadLocal is commonly used to do just such a workaround for SimpleDateFormat).
An additional "gotcha" is the use of a Locale during the construction of the SimpleDateFormat objects- do not remove the Locale configuration. It is not safe to allow the system to choose to use the default Locale because that is user/machine specific. If you do allow it to use the default Locale, you run the risk of transient bugs because your development machine uses a Locale different than the Locale of your end-user. You do not have to use my selected ENGLISH Locale, it is perfectly fine to use a different Locale (you should understand the rules of that Locale and modify the code as appropriate however). Specification of no Locale and utilization of the system default is incorrect however, and likely will lead to many frustrating hours trying to diagnose an elusive bug.
Please understand this solution is not ideal as of Java 8 and the inclusion of the JodaTime based classes, like Instant. I chose to answer using the outdated API's because those were what you seemed concerned with in your question. If you are using Java 8 I strongly urge to learn and utilize the new classes as they are an improvement in almost every conceivable way.

converting date to string and back to date in java

In my program I am trying to convert the date to string to specified format and then back to date. I need the date to be in dd-MMM-yy format. So, I am converting the date to dd-MMM-yy format using SimpleDateFormat like,
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yy");
String bookingDate = sdf.format(myDate);
The result is what I expected, that is 23-May-12 but when I convert the string back to date
using parse(), it is changing to Wed May 23 13:16:14 IST 2012.
Is there any way to convert the string back to date without changing format? I strictly need to pass the date object in the specified format to the query.
when i convert the string back to date using parse(), it is changing to Wed May 23 13:16:14 IST 2012.
That is not true, It converts back to Date correctly, When you try to print Date instance, It invokes toString() method and it has fixed formated output so if you want the formatted date you need to use format() method
In short parse method parses the String to Date there is no property of Date which holds format so you need to use format() method anyhow
How are you passing the date object in your query, if you are simply appending date in your query string why you need to convert your string date back to date object ? And If you are using prepared statement then you need not worry about the format. And as suggested above Date object does not hold any format information
If You strictly need to pass the date object then there is no worries about its format as Date object has understanding with its format either Java, any java framework or SQL..
And if you are passing the date directly in sql query (concatenating) then you can pass Date String in the same format you see in DB, it will process the same correctly.
You can use DateFormat.getDateInstance(DateFormat.SHORT, <locale>).parse(myDate);.
You will, however, have a date in a standard format like dd/MM/yy, not custom. Template depends on which Locale you use.
You can try building your own Pattern using the standard Java Library or through ThreeTen/JSR-310
We now have a more modern way to do this work.
java.time
The java.time framework is bundled with Java 8 and later. See Tutorial. These new classes are inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project. They are a vast improvement over the troublesome confusing old classes, java.util.Date/.Calendar et al.
Date-only class
The new framework offers a class, LocalDate, to represent a date-only without any time-of-day nor time zone.
By the way, using two-digits for year is asking for trouble. I strongly recommend using four-digit years whenever possible. The java.time framework assumes any two-digit years are in the 20xx century, years 2000 to 2099 inclusive.
To parse the string, specify the expected format. You are not using any of the standard ISO 8601 formats, so we must define a format pattern. Specify a Locale that includes the language we expect to find for name-of-month.
// Parse String representation.
String input = "23-May-12";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "d-MMMM-yy" , Locale.ENGLISH ); // Using four "M" characters means we expect the full name of the month.
LocalDate localDate = formatter.parse ( input , LocalDate :: from );
To go the other direction, to generate a string representation of the date value, we can recycle the same formatter.
// Generate String representation.
String output = localDate.format ( formatter );
Dump to console.
System.out.println ( "input: " + input + " → localDate : " + localDate );
System.out.println ( "localDate : " + localDate + " → output: " + output );
When run.
input: 23-May-12 → localDate : 2012-05-23
localDate : 2012-05-23 → output: 23-May-12

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