Date time parsing in Java - java

Given this code...
String date = "11:00 AM";
SimpleDateFormat sdf = new SimpleDateFormat("h:mm a");
sdf.setTimeZone(TimeZone.getTimeZone("US/Eastern")); // --> should be GMT-4
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
Date parse = sdf.parse(date); // -- gives Thu Jan 01 16:00:00 GMT 1970
Why does date parsing give me 16:00 and not 15:00?

You cannot use java.util.Date to store time only. It will assign the 1970 year, which in some cases is incorrect. I would recommend to use org.joda.time.LocalTime for it.

Take day light savings also into consideration. This should give you what you expect
sdf.setTimeZone(TimeZone.getTimeZone("EST5EDT"));

If you are not providing any date portion by default it will be assigned the default Epoche standard date(01 Jan 1970 00:00 Hours is called Epoche standard time and it is taken as standard to measure all the time related calculations as base time).
The getTime() method of java.util.Date class returns the total number of milliseconds between the given date(including time also) and Epoche standard( 01 Jan 1970 00:00 Hours).
Though you are not using getTime() method so it is irrelevant here.
So simply you are getting that time.
And according to GMT it is right.
I thinks it will help you.

Related

Unable to convert dates - LocalDate minus one day

I have a problem with the dates and their passage from Date to LocalDate, mainly the error is with the dates that have the year 1700.
I have tried two different dates and whenever the year is 1700, it puts me one day less.
Date dto = ...;
Instant inst = dto.toInstant();
LocalDate localDate = LocalDate.ofInstant(inst, ZoneId.systemDefault());
Date dto It is a variable that retrieves the date of a query. But the method only gets dto variable as input parameter.
Tue Dec 14 00:00:00 CET 1700 -> Date
1700-12-13T23:00:00Z -> Instant
1700-12-13 -> LocalDate
Sat Jan 01 00:00:00 CET 1994 -> Date
1993-12-31T23:00:00Z -> Instant
1994-01-01 -> LocalDate
I use:
jackson.time-zone: ${TZ:Europe/Madrid}
What is the problem with this year?
This is because whoever produced that Date and ZoneId.systemDefault() have different opinions on what Madrid's offset is from UTC, back in 1700.
Whoever produced that Date mistakenly thinks that Madrid is UTC+1 back in 1700-12-14, so it produced a Date that represents the midnight of 1700-12-14 in the zone UTC+1 ("CET"):
Tue Dec 14 00:00:00 CET 1700
This has a corresponding Instant, because we can pinpoint a certain point in time using this information. This is what toInstant gives you. Instant.toString always displays in UTC (more specifically ISO 8601), so you see:
1700-12-13T23:00:00Z
1700-12-14T00:00:00+01:00 is indeed the same point in time as 1700-12-13T23:00:00Z.
When you do LocalDate.ofInstant, you use ZoneId.systemDefault(). ZoneId.systemDefault() thinks that Madrid had the offset of UTC-0:14:44. This is because Madrid had been observing Local Mean Time, and did not standardise timezones until the 1900s.
Therefore, LocalDate.ofInstant subtracts 14 minutes and 44 seconds from 1700-12-13T23:00:00 to compute what the date would be at offset -0:14:44, and lo and behold, it is still 1700-12-13.
I would recommend that you not to use Date if possible. If what you are doing is related to time at all, you should work with LocalDates directly.

Java Date start epoch

The java.util.Date class is based on the number of seconds since 1 January 1970 00:00 GMT. So why does this code
System.out.println(new Date(0));
print Thu Jan 01 01:00:00 GMT 1970? My local time zone is GMT, so I expected it to print 00:00:00 GMT.
There is an interesting reason for this. Refer (BST Offset bug report)
.
It says, "and the experiment with British Standard Time from 1968 to 1972, by which the time was advanced by one hour from GMT throughout the year." And further: “The local time produced by Date.toString() is historically correct, except for the time zone abbreviation. It should be "BST" (British Standard Time for this case), but it's a known limitation of the current TimeZone implementation.”
This link might help. I'm quite a novice at the Date class, but I figured this could help somehow.
Unix Epoch Time is a system of time describing how much time has elapsed since January 1st, 1970.
Therefore, when you create a new java.util.Date object with 0 milliseconds elapsed, it will return January 1st, 1970.
What you are looking for is here.

LocalDate inconsistency

I am trying to produce a Date object (java.util.Date) from a LocalDate object (java.time.LocalDate) in which I have the following criteria:
Allow a parameter that can subtract a certain number of days from the Date object
Have the Date & Time be the date and time currently in UTC
Have the time at the beginning of the day i.e. 00:00:00
The Timezone stamp (i.e. CDT or UTC) is irrelevant as I remove that from the String
To meet this criteria, I have created a test program, however I am getting interesting results when I modify a certain property of the LocalDate. See code below:
public static void main (String args[]) {
Long processingDaysInPast = 0L;
LocalDate createdDate1 = LocalDate.now(Clock.systemUTC()).minusDays(processingDaysInPast);
LocalDate createdDate2 = LocalDate.now(Clock.systemUTC()).minusDays(processingDaysInPast);
System.out.println(createdDate1);
System.out.println(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC));
System.out.println(Date.from(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC)));
System.out.println((createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
System.out.println(Date.from(createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
}
Output:
2017-08-14
2017-08-14T00:00:00Z
Sun Aug 13 19:00:00 CDT 2017
2017-08-14
2017-08-14T05:00:00Z
Mon Aug 14 00:00:00 CDT 2017
When I add the value Date.from(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC)) I get the expected output of the date, with a 00:00:00 time field. However, if I do not add this parameter, such as: Date.from(createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()) I get the resulting day before , at 19:00:00 why is this?
My main goal from this is to be able to capture a Date object, with the current UTC Date, and the Time zeroed out (StartOfDay).
When you do:
createdDate2.atStartOfDay().atZone(ZoneId.systemDefault())
First, createdDate2.atStartOfDay() returns a LocalDateTime, which will be equivalent to 2017-08-14 at midnight. A LocalDateTime is not timezone-aware.
When you call atZone(ZoneId.systemDefault()), it creates a ZonedDateTime with the respective date (2017-08-14) and time (midnight) in the system's default timezone (ZoneId.systemDefault()). And in your case, the default timezone is not UTC (it's "CDT", so it's getting midnight at CDT - just do System.out.println(ZoneId.systemDefault()) to check what your default timezone is).
To get the date at midnight in UTC, you can replace the default zone (ZoneId.systemDefault()) with UTC (ZoneOffset.UTC):
Date.from(createdDate2.atStartOfDay().atZone(ZoneOffset.UTC).toInstant())
Or (a shorter version):
Date.from(createdDate2.atStartOfDay(ZoneOffset.UTC).toInstant())
Of course you can also do the same way you did with createdDate1:
Date.from(createdDate2.atStartOfDay().toInstant(ZoneOffset.UTC))
They're all equivalent and will result in midnight at UTC.
Just a quick note: short timezone names like CDT or PST are not real timezones.
The API uses IANA timezones names (always in the format Region/City, like America/Chicago or Europe/Berlin).
Avoid using the 3-letter abbreviations (like CDT or PST) because they are ambiguous and not standard.
There are lots of different timezones that can use CDT as abbreviation. This happens because a timezone is the set of all different offsets that a region had, has and will have during history. Just because many places uses CDT today, it doesn't mean they all used in the past at the same periods, nor that it'll be used by all in the future. As the history differs, a timezone is created for each region.

Java Date object parsing precision is off on SimpleDateFormat

I have a date as a string 2016-10-07T12:46:23Z and after parsing to Date object using SimpleDateFormat is converted to Fri Oct 07 08:46:22 EDT 2016 which is 1 sec precision off. Debugging that code it came that it was parsed to Fri Oct 07 08:46:22.998 EDT 2016
SimpleDateFormat to parse as looks like
DATE_FORMAT_ISO8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
DATE_FORMAT_ISO8601.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
and the code to parse looks like
String dateStr = valuesArray.getString(0);
values[0] = RESTUtils.DATE_FORMAT_ISO8601.parse(dateStr);
Any tips how to get proper seconds value after parsing?
The expression new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC")) defines an offset not of zero, but 2 milliseconds, see Javadoc, thus explaining the observed result of "Fri Oct 07 08:46:22.998 EDT 2016".
The constant SimpleTimeZone.UTC is not intended to indicate an offset (as mandated as first argument to SimpleTimeZone-constructor). Its numerical value of "2" is rather a mode to denote how to interprete start or end time parameters for other constructors.
Therefore the correct solution to interprete the trailing "Z" in your input (ISO-8601-notation for zero offset) is:
DATE_FORMAT_ISO8601.setTimeZone(TimeZone.getTimeZone("GMT"));
Alternatively, if you really want to use the class SimpleTimeZone:
DATE_FORMAT_ISO8601.setTimeZone(new SimpleTimeZone(0, "UTC"));
And if you are on Java-8, you could also do this:
Instant instant = Instant.parse("2016-10-07T12:46:23Z");
System.out.println(instant); // 2016-10-07T12:46:23Z
System.out.println(Date.from(instant)); // Fri Oct 07 14:46:23 CEST 2016
You are seeing the second difference when you add the time zone as UTC using SimpleTimeZone, if you comment that part out you will get the exact seconds.
String str = "2016-10-07T12:46:24Z";
SimpleDateFormat DATE_FORMAT_ISO8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
// DATE_FORMAT_ISO8601.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
System.out.println(DATE_FORMAT_ISO8601.parse(str));
SimpleTimeZone is not meant to be used to define the time zone. Per the documentation
SimpleTimeZone is a concrete subclass of TimeZone that represents a
time zone for use with a Gregorian calendar. The class holds an offset
from GMT, called raw offset, and start and end rules for a daylight
saving time schedule. Since it only holds single values for each, it
cannot handle historical changes in the offset from GMT and the
daylight saving schedule, except that the setStartYear method can
specify the year when the daylight saving time schedule starts in
effect.
The correct way to set the timezone is by doing the following
DATE_FORMAT_ISO8601.setTimeZone(TimeZone.getTimeZone("UTC"));

Discrepancy in Converting Date to TimeStamp in java

I have a Date Object in following:
Date date=new Date("Mon, 05 May 2014 12:31:12 +0000")
I want to get Timestamp of date Object then :
date.getTime()
1399293072000
but this value not correct , correct value in following :
1399276872000
//*** for get timestamp use of http://www.epochconverter.com ***\\
why ?
First things first, from the JavaDoc for Date
Date(String s)
Deprecated.
As of JDK version 1.1, replaced by DateFormat.parse(String s).
So the constructor you are using has been deprecated since 1997!
Next, onto the JavaDoc for Date.parse which the construtor uses:
It accepts many syntaxes; in particular, it recognizes the IETF
standard date syntax: "Sat, 12 Aug 1995 13:30:00 GMT". It also
understands the continental U.S. time-zone abbreviations, but for
general use, a time-zone offset should be used: "Sat, 12 Aug 1995
13:30:00 GMT+0430" (4 hours, 30 minutes west of the Greenwich
meridian). If no time zone is specified, the local time zone is
assumed. GMT and UTC are considered equivalent.
Empathsis mine.
So, what timezone are you in? Presumably not UTC.
You should specify local time zone while constructing Date object
Example:
Date date=new Date("Mon, 05 May 2014 12:31:12 GMT+0530");
Using Mon, 05 May 2014 12:31:12 +0000 at http://www.epochconverter.com I get 1399285872000 which is different from your timestamp.
Or you're passing different values, or there's a bug somewhere or
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
where the javadoc for java.util.Date.getTime() doesn't mention leap seconds.

Categories

Resources