Incorrect Parsed Date - java

My code:
DateFormat format = new SimpleDateFormat("dd/MM/YYYY");
Date Today = format.parse(today);
Date Date = format.parse(date);
difference = (Date.getTime() - Today.getTime()) / 86400000;
Math.abs(difference);
System.out.println(String.valueOf("date" + date));
System.out.println(String.valueOf("date" + Date));
System.out.println(String.valueOf("date" + today));
System.out.println(String.valueOf("date" + Today));
The output:
date29/11/2016
dateSun Dec 27 00:00:00 GMT+08:00 2015
date20/11/2016
dateSun Dec 27 00:00:00 GMT+08:00 2015
I have problems while parsing the date, the original date is 29/11/2016, however when parsed, the date becomes Sun Dec 27 00:00:00 GMT+08:00 2015.
This problem appears in my whole program whenevr it's related to date.

Format dd/MM/YYYY should be dd/MM/yyyy. See javadoc of SimpleDateFormat: y = Year, Y = Week year. – Andreas 12 mins ago
Thanks resolved.

I know you got your solution from Andreas’ comment already. What I want to do here is take a step back and suggest a few improvements to your code. Feel free to ignore.
Most importantly I suggest you throw the long outdated classes Date, DateFormat and SimpleDateFormat overboard and start using their modern replacements. These came out in the java.time package early in 2014. These also offer a much more straightforward and clear way of calculating the difference.
Follow the convention that says that a variable name begins with a lowercase letter. Specifically, in the same source file to use a class called Date and two variable called date and Date is bound to cause confusion.
Like Henry I also think you intended difference = Math.abs(difference);.
Your calls to String.valueOf() are superfluous and just seem to make the code a bit harder to read. Drop them.
For the sake of the example, in the code I suggest below, I am deliberately using your incorrect date format pattern string, dd/MM/YYYY.
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd/MM/YYYY");
LocalDate todayAsLocalDate = LocalDate.parse(today, format);
LocalDate dateAsLocalDate = LocalDate.parse(date, format);
difference = ChronoUnit.DAYS.between(todayAsLocalDate, dateAsLocalDate);
difference = Math.abs(difference);
System.out.println("date " + date);
System.out.println("date " + dateAsLocalDate);
System.out.println("date " + today);
System.out.println("date " + todayAsLocalDate);
System.out.println(difference);
As the code stands now, it throws a java.time.format.DateTimeParseException: Text '20/11/2016' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {WeekBasedYear[WeekFields[SUNDAY,1]]=2016, MonthOfYear=11, DayOfMonth=20},ISO of type java.time.format.Parsed. When the code is incorrect, I much prefer an exception over an incorrect result that might go unnoticed. So this is better than what SimpleDateFormat gave you.
While the message is not easy to read, the bit to notice is WeekBasedYear. Week-based years are only useful with week numbers, you intended none of that. If you compare with the documentation, you will see that uppercase Y in the pattern is week-based-year while lowercase y is year-of-era. So let’s correct:
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd/MM/yyyy");
Now the code prints:
date 29/11/2016
date 2016-11-29
date 20/11/2016
date 2016-11-20
9
We note one final advantage of the modern classes: you can have a date without a time-of-day when this is what you need, again giving code that models your requirements more precisely and thereby leaves less room for confusion.
Question: can I use the modern classes with my Java version?
If using at least Java 6, you can.
In Java 8 and later the new API comes built-in.
In Java 6 and 7 get the ThreeTen-Backport library, the backport of the new classes (that’s “ThreeTen” for JSR 310, where the modern API was first defined).
On Android, use the Android edition of ThreeTen-Backport. It’s called ThreeTenABP, and I think that there’s a wonderful explanation in this question: How to use ThreeTenABP in Android Project.

Related

Anomaly in hardcoding date in Java

There is an anomaly I have observed while setting dates in Java.
I am trying the following:-
Date date1 = new Date("10/12/2018");
So when I am printing the date, it is coming of future
It was printing this date:- 14 June 2019.
When I am doing the following:-
Date date1 = new SimpleDateFormat("dd/MM/yyyy").parse("10/12/2018");
It is showing the exact date. Can anyone please explain why this happened?
Thanks in advance.
java.time
To hardcode a date use the following:
LocalDate date2 = LocalDate.of(2018, Month.OCTOBER, 12);
System.out.println("Harcoded date: " + date2);
You will never get in doubt which is month, day and year. Output is:
Harcoded date: 2018-10-12
You should avoid the poorly designed and long outdated Date class and even more its deprecated constructors. Instead I am using LocalDate from java.time, the modern Java date and time API. Also a LocalDate represents a calendar date (without time of day), contrary to Date, which despite its name represents a point in time.
BTW I could not reproduce your problem. I get Fri Oct 12 00:00:00 CEST 2018 (which also agrees with the documentation, though this part of the documentation is very hard to read and understand).
Link: Oracle tutorial: Date Time explaining how to use java.time.
The Date() constructor (Note: it's deprecated !) doesn't know what is month and year.
USA: MM/dd/yyyy while Europe it's dd/MM/yyyy.
In the second form you are explicit. In the the first form it picks the wrong one.

ParseException when trying to parse Date string

I have a piece of code written to parse date string -
DateFormat cal = new SimpleDateFormat("yyyy-MM-dd hh:mm");
cal.setLenient(false);
try {
cal.parse("2018-01-01 14:42");
}
catch (Exception e)
{
e.printStackTrace();
}
}
But I get an exception saying -
java.text.ParseException: Unparseable date: "2018-01-01 14:42"
at java.base/java.text.DateFormat.parse(DateFormat.java:388)
at MyClass.main(MyClass.java:10)
I am not sure why I am seeing this error as the date string and the format given is right. Please help
From the documentation https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html:
Lowercase h in the SimpleDateFormat indicates hour in the 12 hour format, whereas 24-hour format is indicated with uppercase H. As 14 > 12, the date 14:42 fails to be parsed.
You should be using HH instead of hh for hour pattern if the hour is displayed in 24 hour format.
See the documentation below for more information.
https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html
hh is used for the time of the day with hours going from 1 to 12. 14 is not a valid hour for this kind of hour-representation, so you have to use HH or kk. The former is used for times that are shown from 0-23, the latter for times shown between 1-24. Most likely you have to use HH or H/k if the single digit hours aren't preceded by a 0.
TL;DR
DateTimeFormatter cal = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm");
LocalDateTime.parse("2018-01-01 14:42", cal);
This runs without exception or other error.
java.time
The date-time classes you use, DateFormat and SimpleDateFormat, are long outdated and furthermore notoriously troublesome. I recommend you stop using them immediately. Instead use java.time, the modern Java date and time API. It came out nearly four years ago after having been described in Java Specification Request (JSR) 310 (a name that somehow still clings to the API).
As others have correctly pointed out, your error was that you used lowercase hh in your format pattern string, where you should have used uppercase HH for hour of day. Just one little example of where the modern classes try to be more helpful, try the same. If I insert hh in the format pattern in the code above, my program crashes (because there is no try-catch construct) with an DateTimeParseException with the following message:
Text '2018-01-01 14:42' could not be parsed: Invalid value for
ClockHourOfAmPm (valid values 1 - 12): 14
While perhaps still a bit esoteric, it is very precise. And I would dare hope that in combination with the documentation it would tell you what you did wrong.
The exception is unchecked, so no try-catch is required around the parsing. On the other hand, you may use one if you like (and if you are not very certain that the format of your date-time string is correct, you should).
Links
Oracle tutorial: Date Time, explaining how to use java.time.
Java Specification Request (JSR) 310, where the modern date and time API was first described.

String conversion into time (only hh:mm)

I want my String "10:10" to be converted into time in a format of hh:mm instead of MM/dd/yyyy hh:mm:ss aa
Date date;
SimpleDateFormat sdf;
sdf = new SimpleDateFormat("hh:mm");
try
{
date = sdf.parse(a.getString("time").toString());
Log.d(TAG, "onCreate: "+date);
Log.d(TAG, "onCreate: "+a.getString("time"));
}
catch (ParseException e) {
e.printStackTrace();
}
But i am getting this in my logcat
D/MTAG: onCreate: Thu Jan 01 10:00:00 GMT+05:00 1970
D/MTAG: onCreate: 10:00
String timeString = "10:10";
LocalTime time = LocalTime.parse(timeString);
System.out.println(time);
This prints
10:10
I am cheating a bit, though. The way I read your question, you asked for a date-time object with the format HH:mm in it. Neither a LocalTime object (used in the above snippet) nor a Date (used in your code) can have a format in it. What you get when you concatenate the Date to a string or print the LocalTime is the result of the object’s toString method, and you cannot change this method (only in subclasses, and you don’t want that). In other words, when you want a specific format, you need to have that format in a string outside the date-time object.
The lucky part is that LocalTime.toString() produces the format you want (as long as the seconds and fraction of second are zero; otherwise they would be in the string too).
Will that work on your Android device? It will. LocalTime is a class of JSR-310 also known as java.time, the modern Java date and time API introduced nearly 4 years ago, early in 2014. JSR-310 has been backported to Java 6 and 7 in ThreeTen Backport, which in turn has been adapted to Android in ThreeTenABP. So get ThreeTenABP, add it to your project and start enjoying how much nicer it is to work with than the outdated date and time classes.
PS There’s a bug in your format pattern string in the question: Lowercase hh is for hour within AM or PM from 1 through 12, which works nicely when the hours are 10, but not always. I am convinced that you want uppercase HH for hour of day in the interval 0 through 23. When I run your code with a string of 12:12, I get Thu Jan 01 00:12:00 CET 1970. The hours are 0, not 12.
Links
Oracle tutorial: Date Time, explaining how to use java.time.
ThreeTen Backport project
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Java Specification Request (JSR) 310, where the modern date and time API was first described.
Date and time formats are specified by date and time pattern strings.
Within date and time pattern strings, unquoted letters from 'A' to 'Z'
and from 'a' to 'z' are interpreted as pattern letters representing
the components of a date or time string. Text can be quoted using
single quotes (') to avoid interpretation. "''" represents a single
quote. All other characters are not interpreted; they're simply copied
into the output string during formatting or matched against the input
string during parsing.
Read Document
Try this:
DateFormat aFormatter = new SimpleDateFormat("HH:mm");
Date dt = aFormatter.parse("10:10");
Calendar aCalander = Calendar.getInstance();
aCalander.setTime(dt);
int hour = aCalander.get(Calendar.HOUR);
int minute = aCalander.get(Calendar.MINUTE);
When a Date is created, it will be in the format of "Thu Jan 01 10:00:00 GMT+05:00 1970" as you mention in your output. So if you want to display and play around with the format of the date you should use the format method in SimpleDateFormat. I hope the below code help you understand better.
//formatting date in Java using SimpleDateFormat
String date_s = "10:10";
SimpleDateFormat dt = new SimpleDateFormat("hh:mm");
Date date = dt.parse(date_s);
System.out.println(date);
System.out.println(dt.format(date));

yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z' convert to date format

I receive the date from API in this format:
yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z'
and convert it within this way:
String rawDate = "2017-05-11T15:46:48.2226756Z";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z'", Locale.getDefault());
Date date = simpleDateFormat.parse(rawDate);
System.out.println(date); //Thu May 11 16:23:54 PDT 2017
However the date output is like that:
Thu May 11 16:23:54 PDT 2017
Output supposed to be:
Thu May 11 15:46:48 PDT 2017
How to convert the raw date properly?
SimpleDateFormat cannot handle any other number of decimals on the seconds than three (milliseconds), so there is no way to have it parse your string correctly. Furhermore the newer Java date and time classes are generally much more programmer-friendly and convenient. And they come with nanosecond precision (9 decimals on the seconds). So I am suggesting that you consider moving on to them.
As already commented Z means Zulu time zone, also known as UTC. So 2017-05-11T15:46:48.2226756Z means 15:46:48 UTC, equal to 8:46:48 Pacific Daylight Time. Your format is the ISO 8601 format for an instant, which the Instant class understand as its default, so parsing is easy:
Instant instant = Instant.parse(rawDate);
The result is
2017-05-11T15:46:48.222675600Z
Only thing to note about this is the two added zeroes. The toString method prints decimals in groups of three, enough groups to render the full precision. So with 7 decimals it prints 9.
To get the date in the Pacific time zone:
ZonedDateTime dateTime = instant.atZone(ZoneId.of("America/Los_Angeles"));
The result is what I predicted:
2017-05-11T08:46:48.222675600-07:00[America/Los_Angeles]
Now assume you got your raw date-time string from someone who misunderstood and really meant Thu May 11 15:46:48 PDT 2017 (it wouldn’t be the first time in history). Then you need to convert it to that. Again, while this would be cumbersome with the oldfashioned classes, it goes smoothly with the newer ones:
ZonedDateTime dateTime = instant.atOffset(ZoneOffset.UTC)
.atZoneSimilarLocal(ZoneId.of("America/Los_Angeles"));
The result is the one you asked for (except I am giving you all the decimals too):
2017-05-11T15:46:48.222675600-07:00[America/Los_Angeles]
For Android you get the newer date and time classes from the ThreeTenABP library.
Links
Oracle Tutorial: Trail: Date Time
The date and time classes for Android: ThreeTenABP
Question How to use ThreeTenABP in Android Project
The problem is that 'S' stands for milliseconds. So, in your case, you are telling it that the time is 15 hours, 46 minutes, 48 seconds and 2226756 milliseconds. If you add 2226756 milliseconds, i.e. 2226 seconds and 756 milliseconds to 15:46:48, you indeed get 16:23:54.
The easiest solution is probably to just find the period in your string, and truncate the string three places, later, i.e. convert it to:
2017-05-11T15:46:48.222
You can achieve this with the following line:
rawDate = rawDate.substring(0, rawDate.indexOf('.') + 4);
And then parse it with
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.getDefault());
Note that this does not correctly round the microseconds. In your case, for example, 222.6756ms should be rounded up to 223ms, not down to 222ms. If this matters, you can do this manually by examining the first dropped digit to see if it's 5 or above and adding a millisecond to date.
Update (re: Basil Bourque):
If you would like to actually respect the time-zone identifier in your time-string (which indicates UTC as explained below by Ole V.V.), you can simply add 'UTC' to the end of the string and parse it with that timezone in older versions of Java without using any additional libraries:
rawDate = rawDate.substring(0, rawDate.indexOf('.') + 4) + "UTC";
SimpleDateFormat sDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSz",
Locale.getDefault());
Date date = sDF.parse(rawDate);
You can just use below to parse.
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault());

How to convert UTC to PST in java [duplicate]

This question already has answers here:
Convert GMT to IST in java?
(5 answers)
Closed 6 years ago.
I am trying to convert time zone from UTC to GMT in java. I have tried several times and even used your guided method too. I am getting my output with correct timing in GMT format but along with "PDT 2012" written with it. Why so..?? I have tried hundreds of methods but can't get rid of it.
Please help me.
Thanks
For all Date / or DateTime related operations in Java I would recommend to use JodaTime Library
It is very useful to use Date/time with different point of views (calendar, timezone) and for computation as well: adding/substracting months, years, days and so on...
Since Java 8, an equivalent (improvement) of JodaTime is included in the JDK under the new package java.time (JSR-310) and no more needed to add it as dependency.
The author of JodaTime explains in his blog the difference between JodaTime and JSR-310.
Perhaps the following will be a starting point. It converts your current date to GMT:
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
Calendar cal = Calendar.getInstance();
System.out.println(cal.getTime());
TimeZone currentTimeZone = cal.getTimeZone();
int offset = currentTimeZone.getOffset(cal.getTimeInMillis());
Date adjustedTime = new Date(cal.getTimeInMillis() - offset);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormat.format(adjustedTime));
A couple of notes:
You are probably not able see the PST change to UTC because you don't set the timezone on the date format
You shouldn't really use the abbreviations like "GMT" anymore. It is better to use the full name in the id field.
You'll have to be a bit more creative if you happen to run the above code on a system that has its default time already set to GMT.

Categories