SimpleDateFormat does not parse correctly - java

String current = "07:00:00.160"
DateFormat df2 = new SimpleDateFormat("HH:mm:ss.SSS");
DateList.add(df2.parse(current));
Returns [Thu Jan 01 07:00:00 GMT 1970]
I have tried this as well
Date currentdate;
currentdate = df2.parse(current);
df2.format(currentdate);
DateList.add(currentdate);
Returns also
[Thu Jan 01 07:00:00 GMT 1970]
and I have also tried using df2.setLenient(false);

java.time.LocalTime
I recommend that you use java.time, the modern Java date and time API, for your time work. The class to use for time of day is LocalTime.
We don’t even need to specify a formatter for parsing your string since it is in the default format for a time of day (also laid down in the ISO 8601 standard).
String current = "07:00:00.160";
LocalTime time = LocalTime.parse(current);
System.out.println(time);
Outout:
07:00:00.160
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601

Related

Oracle Timestamp value is not converting to the java datetime

I have a query for an Oracle database that returns a datetime column. In the java method, the column is converted to a string.
A portion of the code looks like this:
ResultSet rs;
HashMap<String, String> hm=new HashMap<String, String> ();
hm.put("SchEndDate2", rs1.getString("END_DT_TM_GMT"));
When I view the strings value in the debugger it looks like this: "2019-07-04 11:00:00.0"
I need to convert this string to the datetime format of this: "yyyy-MM-dd'T'HH:mm"
I tried this SimpleDateFormat to complete this but when I convert the string to the format it returns the dateTime in Eastern Daylight Time and not GMT.
The value after going thru the conversion is this: "Thu Jul 04 07:00:00 EDT 2019"
This is the code that I am using to convert the string to a DateTime.
EndDate=map.get("SchEndDate2");
//EndDate : **"2019-07-04 11:00:00.0"**
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
Date databaseDateTime = formatter.parse(EndDate);
//databaseDateTime: **"Thu Jul 04 07:00:00 EDT 2019"**
Why is the format incorrect and the timezone not correctly set?
Two points.
Don’t fetch your date and time as a string from Oracle. Fetch a proper date-time object. In this case a LocalDateTime.
Don’t use SimpleDateFormat, TimeZone and Date. Those classes are poorly designed and long outdated, the first in particular notoriously troublesome. Use java.time, the modern Java date and time API.
In code:
ResultSet rs = // …;
LocalDateTime dateTime = rs.getObject("END_DT_TM_GMT", LocalDateTime.class);
String databaseDateTimeAsString = dateTime.toString();
System.out.println(databaseDateTimeAsString);
Example output:
2019-07-04T11:00
It’s not quite the output format that you asked for, but it most likely will serve your purpose. The format you asked for is ISO 8601. So is the output I have given you. In the ISO 8601 standard, including the seconds and fraction of second when they are 0 is optional. If you insist on including them, use a formatter. For example:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS");
String databaseDateTimeAsString = dateTime.format(formatter);
2019-07-04T11:00:00.000
Using rs.getObject() for getting a LocalDateTime as shown requires a JDBC 4.2 compliant database driver. You probably have got that. In case you haven’t and you cannot upgrade, use:
LocalDateTime dateTime = rs.getTimestamp("END_DT_TM_GMT").toLocalDateTime();
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601
Try converting the Date object to an Instant. Here's an example showing your input string first converted to a Date, and then converting that to an Instant. The date contains the timezone-specific rendering, but the instant does not.
String input = "2019-07-04 11:00:00.0";
System.out.println("input: " + input);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
Date date = formatter.parse(input);
System.out.println("date: " + date);
Instant instant = date.toInstant();
System.out.println("instant: " + instant);
And here's the output:
input: 2019-07-04 11:00:00.0
date: Thu Jul 04 05:00:00 MDT 2019
instant: 2019-07-04T11:00:00Z

How to parse date with only month and year with SimpleDateFormat

I am working with expiration date of card. I have a API where I will get expiration date in "yyMM" format as "String". Here I am trying to use
SimpleDateFormat with TimeZone.getTimeZone("UTC")
So my code is like
String a= "2011";
SimpleDateFormat formatter = new SimpleDateFormat("yyMM");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = formatter.parse(a);
System.out.println(date);
Now problem is, when I am passing 2011 the out it gives is Sat Oct 31 17:00:00 PDT 2020
Here you can see I am passing 11 as month but it is converting it to Oct instead of Nov.
Why?
And what other options I can use to convert string with yyMM to Date with Timezone?
You should use the Java 8 YearMonth class.
String a = "2011";
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("yyMM");
YearMonth yearMonth = YearMonth.parse(a, inputFormat);
DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("MMMM yyyy");
System.out.println(yearMonth.format(outputFormat));
Output
November 2020
You parsed it fine, but it's printed in PDT, your local timezone.
Sat Oct 31 17:00:00 PDT 2020
Well, Date doesn't track timezones. The Calendar class does, which is internal to the formatter. But still, default print behavior is current timezone.
If you logically convert this output back to UTC, and it will be November 1 since PDT is UTC-7.
Basically, use java.time classes. See additional information here How can I get the current date and time in UTC or GMT in Java?

SimpleDateFormat.parse() converts DTstring to local time. Can be converted to source's time?

I have followed this SO answer for datetime conversion of 8601.
I will cite an example straight from w3 :
1994-11-05T08:15:30-05:00 corresponds to November 5, 1994, 8:15:30 am, US Eastern Standard Time.
1994-11-05T13:15:30Z corresponds to the same instant.
And this is what I run in android
SimpleDateFormat sdfSource = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ");
dateTime = sdfSource.parse("2014-03-06T11:30:00-05:00");
System.out.println(dateTime); //Thu Mar 06 18:30:00 EET 2014
Obviously .parse()'s output is the local aware datetime. There has been a conversion from EST(-05:00) to EET (+02:00) since now I am in this timezone. However I do not want this auto-convertion.
Is there a way to parse a datetime string inyyyy-MM-dd'T'HH:mm:ssZZZZZ format and display THAT timezone's datetime? Preferable output:
Thu Mar 06 11:30:00 EST 2014
The EST and my location is an example. It can be any other timezones as well.
Internally Date objects are in UTC and that's what they're parsed to.
You cannot retrieve the original timezone from the Date but you can attempt to retrieve it from the original ISO-8601 stamp, and use it when formatting.
When you convert it to a string with toString(), it uses your local settings to format the date. If you want a specific representation, use a formatter to format the output, e.g.
int rawTimeZoneOffsetMillis = ...; // retrieve from ISO-8601 stamp and convert to milliseconds
TimeZone tz = new SimpleTimeZone(rawTimeZoneOffsetMillis, "name");
DateFormat outputFormat = DateFormat.getDateTimeInstance();
outputFormat.setTimeZone(tz);
System.out.println(df.format(dateTime));
ISO-8601 timestamps are not completely parseable with SimpleDateFormat. This answer has some code to work around some of the limitations.
Use sdfSource.setTimeZone() method
SimpleDateFormat sdfSource = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ");
sdfSource.setTimeZone(TimeZone.getTimeZone("EST")); //give the timezone you want
dateTime = sdfSource.parse("2014-03-06T11:30:00-05:00");
System.out.println(dateTime); //Thu Mar 06 18:30:00 EET 2014
This should do fine.
Although you should not be worried while parsing the date as it is parsed to correct value can be displayed in any format or timezone you want.
SimpleDateFormat sdfSource = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ");
sdfSource.setTimeZone( TimeZone.getTimeZone( "EST" ) );
dateTime = sdfSource.parse("2014-03-06T11:30:00-05:00");
System.out.println(sdfSource.format(dateTime)); //Thu Mar 06 18:30:00 EET 2014

Formatting a date in java

I have the two Date objects which I am trying to format from being in MM/DD/YYYY format to "yyyy-mm-dd HH:mm:ss" format.
The current approach I am using is to first format those dates using SimpleDateFormat which will return two Strings, then I have to convert this string back to Date to get the formatted final Date objects.
So I was wondering if there was a simpler way to change the Date object format without going in many steps?
Thanks
The format is irrelevant. Date simply represents the number of milliseconds since the Unix epoch.
Remember, Date has no concept of format, it doesn't care.
You should simply format the Date object with whatever formatters you need...
For example...
Date date = new Date();
System.out.println(date);
System.out.println(DateFormat.getDateTimeInstance().format(date));
System.out.println(new SimpleDateFormat("dd/MM/yyyy").format(date));
System.out.println(new SimpleDateFormat("yyyy MMMM EE").format(date));
System.out.println(new SimpleDateFormat("EEEE MMMM yyyy").format(date));
System.out.println(date);
Outputs...
Wed Jan 22 11:55:18 EST 2014
22/01/2014 11:55:18 AM
22/01/2014
2014 January Wed
Wednesday January 2014
Wed Jan 22 11:55:18 EST 2014
Note how the first and last values don't change. Date has no internal concept of format, that's the responsibility of the formatter.
For example, if I took the String value 22/01/2014 and parsed it back to a Date using SimpleDateFormat
Date date = new SimpleDateFormat("dd/MM/yyyy").parse("22/01/2014");
And then outputted the date value...
System.out.println(date);
It would output something like...
Wed Jan 22 00:00:00 EST 2014
The format has being lost. It would need to use an appropriate formatter to change what is displayed

How to parse month full form string using DateFormat in Java?

I tried this:
DateFormat fmt = new SimpleDateFormat("MMMM dd, yyyy");
Date d = fmt.parse("June 27, 2007");
error:
Exception in thread "main" java.text.ParseException: Unparseable date: "June 27, 2007"
The java docs say I should use four characters to match the full form.
I'm only able to use MMM successfully with abbreviated months like "Jun" but i need to match full form.
Text: For formatting, if the number
of pattern letters is 4 or more, the
full form is used; otherwise a short
or abbreviated form is used if
available. For parsing, both forms are
accepted, independent of the number of
pattern letters.
https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html
You are probably using a locale where the month names are not "January", "February", etc. but some other words in your local language.
Try specifying the locale you wish to use, for example Locale.US:
DateFormat fmt = new SimpleDateFormat("MMMM dd, yyyy", Locale.US);
Date d = fmt.parse("June 27, 2007");
Also, you have an extra space in the date string, but actually this has no effect on the result. It works either way.
LocalDate from java.time
Use LocalDate from java.time, the modern Java date and time API, for a date
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMMM d, u", Locale.ENGLISH);
LocalDate date = LocalDate.parse("June 27, 2007", dateFormatter);
System.out.println(date);
Output:
2007-06-27
As others have said already, remember to specify an English-speaking locale when your string is in English. A LocalDate is a date without time of day, so a lot better suitable for the date from your string than the old Date class. Despite its name a Date does not represent a date but a point in time that falls on at least two different dates in different time zones of the world.
Only if you need an old-fashioned Date for an API that you cannot afford to upgrade to java.time just now, convert like this:
Instant startOfDay = date.atStartOfDay(ZoneId.systemDefault()).toInstant();
Date oldfashionedDate = Date.from(startOfDay);
System.out.println(oldfashionedDate);
Output in my time zone:
Wed Jun 27 00:00:00 CEST 2007
Link
Oracle tutorial: Date Time explaining how to use java.time.
Just to top this up to the new Java 8 API:
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("MMMM dd, yyyy").toFormatter();
TemporalAccessor ta = formatter.parse("June 27, 2007");
Instant instant = LocalDate.from(ta).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
Date d = Date.from(instant);
assertThat(d.getYear(), is(107));
assertThat(d.getMonth(), is(5));
A bit more verbose but you also see that the methods of Date used are deprecated ;-) Time to move on.
val currentTime = Calendar.getInstance().time
SimpleDateFormat("MMMM", Locale.getDefault()).format(date.time)

Categories