Changing Java Timestamp format causes a change of the timestamp - java

I'm a bit puzzled regarding the Java timestamp formatting functions as they seem to change the timestamp by a few minutes.
My Pivotal CloudFoundry app writes a new entry into a PostgreSQL 9.4.5 database. Doing so, I let PostgreSQL generate and store a timestamp for that entry (within the SQL statement I use 'now()' for that particular column).
All that works fine so far. Problems arise when I read the entry with my app because I have to format the timestamp to ISO 8601 (company policy) and this seems to change the timestamp. I've used this code:
public String parseTimestamp(String oldDate) {
System.out.println("String oldDate: " + oldDate);
TimeZone timeZone = TimeZone.getTimeZone("Europe/Berlin");
SimpleDateFormat oldDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSS");
SimpleDateFormat newDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
newDateFormat.setTimeZone(timeZone);
Date tempDate = null;
try {
tempDate = oldDateFormat.parse(oldDate);
} catch (ParseException e) {
//TODO
}
System.out.println("tempDate before format(): " + tempDate);
String newDate = newDateFormat.format(tempDate);
System.out.println("tempDate after format(): " + tempDate);
System.out.println("String newDate: " + newDate);
return newDate;
}
Output:
String oldDate: 2018-06-18 13:07:27.624828+02
tempDate before format(): Mon Jun 18 13:17:51 CEST 2018
tempDate after format(): Mon Jun 18 13:17:51 CEST 2018
String newDate: 2018-06-18T13:17:51Z
As you can see, the timestamp changed from 13:07 to 13:17. All the other queried entries also show a difference, varying between ~2 to 10 minutes. However, when I re-run the query, each difference stays the same. OPs told me that all involved systems have synchronised time and I'm not sure if system time should play a role here at all.
Does someone know what is going on?

First, I was really puzzled and thought, you might have found some kind of bug in SimpleDateFormat. Your code can be reduced to the following lines to show the same behaviour:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSS");
String str = "2018-06-18 13:07:27.624828+02";
System.out.println(str);
System.out.println(format.parse(str));
Result:
2018-06-18 13:07:27.624828+02
Mon Jun 18 13:17:51 CEST 2018
The parsed Date object got ten additional minutes (and some seconds).
Taking a closer look reveals the problem - it is NOT a bug in JDK:
Your millisecond-part is 624828 - these are six(!) digits (not three). 624828 milliseconds are about 624 seconds, which are 10 minutes and 24 seconds.
The SimpleDateFormat correctly summed up this additional seconds and minutes.
What's wrong too: Your date format contains five digits for the milliseconds part.
Solution:
The (new) Java Time API can handle larger fractions of a second - and also convert easily between different time zones:
String str = "2018-06-18 13:07:27.624828+02";
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSx");
OffsetDateTime date = OffsetDateTime.parse(str, pattern);
System.out.println(date);
System.out.println(date.withOffsetSameInstant(ZoneOffset.UTC));
Result:
2018-06-18T13:07:27.624828+02:00
2018-06-18T11:07:27.624828Z

Your input date contains micro seconds but SimpleDateFormat supports only milli seconds (up to 3 digits). When parsing the value with the flag lenient enabled the complete 6 digits are evaluated as micro seconds. So at the end you have 624 seconds that are added to the date additionally.
You can try to use the SSSSSS pattern with DateTimeFormatter that has been introduced in Java 8.
But you may have further issues. Your code parses the input date without the time zone information +02 that is included at the end. You should add one letter X for the ISO8601 time zone format. When formatting the date for outputting you use letter 'Z' that indicates time zone UTC. But you set time zone CET (Berlin). So the output date is not in UTC. The correct ouput in UTC for the specified input date is:
2018-06-18 11:07:27Z

Related

Selenium JAVA : How to validate a frequently changing data in the front end?

The website that I am automating has a data which is something like,
"Delivery Sep 06 Thursday"
The date keeps changing everyday. I now have to validate it's presence and the message format.
Any help on this is appreciated.
Try this:
public String getCurrentDate() {
//Delivery Sep 06 Thursday
String format = "MMM dd EEEEE";
SimpleDateFormat formatCurrentDate = new SimpleDateFormat(format, Locale.ENGLISH);
Calendar userDate = Calendar.getInstance();
return formatCurrentDate.format(userDate.getTime());
}
public void checkDeliveryDate() throws Exception {
String searchString = "Delivery " + getCurrentDate();
driver.isElementPresent(By.xpath("//div[.='"+searchString+"'])"));
}
You have 2 options:
If you know what's a formula behind expected date (for example: always same day; always 3 days from now, or even some more complicated rules), then your test can generate expected date much like the site does, and validate that date displayed on the site is the same as your expected date.
If you don't know the formula, it's too complicated, or changes too often, then you can validate 3 things:
That date is displayed in proper format (e.g. you could check that its format is Delivery MMM DD EEEE)
Date and day of the week match (e.g. check that Sep 06 is indeed Thursday)
Date is within acceptable range (e.g. +/- week from current date, or whatever makes sense)
Those are general rules. If you want a more specific advice, please post HTML code, and some logic behind expected dates.

Transform Date to JSON

I got the following date input Sat May 23 18:09:05 EEST 2015 ,
how can i convert it into this format of json
"PublishedTo":"\/Date(1432645752000+0200)\/"
The seems like the date/time wire format used in WCF. From MSDN it states:
DateTime values appear as JSON strings in the form of
"/Date(700000+0500)/", where the first number (700000 in the example
provided) is the number of milliseconds in the GMT time zone, regular
(non-daylight savings) time since midnight, January 1, 1970. The
number may be negative to represent earlier times. The part that
consists of "+0500" in the example is optional and indicates that the
time is of the Local kind - that is, should be converted to the local
time zone on deserialization. If it is absent, the time is
deserialized as Utc. The actual number ("0500" in this example) and
its sign (+ or -) are ignored.
If so, this issue has been discussed several times on SO.
.net JSON Date format
POSTing a DateTime from Android to a WCF RESTful JSON Service
Try this:
String givenDateString = "5/28/2015";
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
try {
Date mDate = sdf.parse(givenDateString);
long timeInMilliseconds = mDate.getTime();
System.out.println("Date in milli :: " + timeInMilliseconds);
} catch (ParseException e) {
e.printStackTrace();
}

SimpleDateFormat ignoring DST offset in Android

In Central Europe, the current time zone (as of 3rd October) is:
CEST / UTC+2
But when I create an instance of SimpleDateFormat in Android now ...
dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
... it returns CET / UTC+1 as the time zone. So it's ignoring the DST offset which must still be there at the moment. Why is this?
Furthermore, when using the (now deprecated) method getTimezoneOffset() of Date instances, it returns inconsistent results:
(new Date()).getTimezoneOffset() correctly returns -120 (2 hours) while dateTimeFormat.parse("2012-10-03T22:00:00.000+0000").getTimezoneOffset() returns -60 (1 hour).
How can this happen? Am I doing something wrong or is this a known bug?
Note: I've heard that there are libraries which offer better time calculations (e.g. Joda Time), and I've heard that quite often now ;) But using some workarounds, you can just as easily use the built-in Java time library.
And, of course, the timezone is correctly set on my machine.
I don't know if I have properly understood your use case, but from what I have understood when I try this code.
public static void main(String[] args) {
SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String date="2012-10-03T22:00:00.000+0000";
try {
System.out.println(dateTimeFormat.getTimeZone().getDisplayName());
System.out.println("Today : "+new Date().toString()+ ", Timezone Offset :" +
+(new Date()).getTimezoneOffset());
System.out.println("Parsed Date : "+
dateTimeFormat.parse(date).toString()
+ ", Timezone Offset : "
+dateTimeFormat.parse(date).getTimezoneOffset());
} catch (ParseException e) {
e.printStackTrace();
}
}
I am getting an consistent Output i.e :
Central European Time
Today : Wed Oct 03 09:44:56 CEST 2012, Timezone Offset : -120
Parsed Date : Wed Oct 03 23:00:00 CEST 2012, Timezone Offset : -120
I have just switched to JODA with is great.
It also works good on Android with the comments in this link:
Android Java - Joda Date is slow
That make it run faster.

How to convert Date and Time Combination into Days in Java

I have Date and Time combination as 2012-02-28T13:10:50Z which I got from the WebService.
I need to convert that String into number of Days.
You could parse the timestamp with SimpleDateFormat and convert the milli seconds Date.getTime() into days by dividing by 24*60*60*1000L -> number of days since 1/1/1970
To parse the date, use
import java.text.SimpleDateFormat;
SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ss'Z'");
I'm not sure about the trailing Z.
date = sdf.parse (d);
// java.util.Date = Tue Feb 28 13:10:50 CET 2012
You may find this helpful, this is specific to the XML Schema date/time:
DatatypeFactory.newXMLGregorianCalendar
Follow the link on that page to the class XMLGregorianCalendar for details on how to extract all components.

Get server date problem

I have problem with getting server date (linux server). When I use linux 'date' command I get properly date value (real date). If I modify some file
on server, modify date is also properly (real date). But if i use java code System.out.println(new Date()) on server I get date with 1 hour difference
i.e. linux 'date' command result = Wed Sep 16 08:48:25 CEST, System.out.println(new Date()) result = Wed Sep 16 07:48:25 GMT+1
Is this linux configuration problem or wrong getting date using java.
Thanks
date --rfc-2822; date +%s
Wed, 16 Sep 2009 09:59:36 +0200
1253087976
System.out.println(new SimpleDateFormat("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z").format(new Date()));
System.out.println(new Date().getTime() / 1000);
16 wrz 2009 09:00:33 +0100
1253088033
You must make sure you use the correct time zone before using Date (or Calendar, for that matter - wasn't Date deprecated?).
For instance:
/* Skipping the boring class def part. */
public static void main(String[] args) {
Date date = new Date();
DateFormat myDateFormat = new SimpleDateFormat();
TimeZone firstTime = TimeZone.getTimeZone(args[0]);
myDateFormat.setTimeZone(firstTime);
System.out.println("-->"+args[0]+": " + myDateFormat.format(date));
}
the argument then can be your desired time zone, for example "IST", "GMT", or whatever.
This is probably a timezone/daylight savings issue. Use:
java.util.Timezone.getDefault()
to see which timezone is Java configured to use and whether daylight savings apply or not.
I suggest you upgrade your Java installation. Your JRE likely doesn't have the latest daylight savings rules in place. Java gets the time since the epoch, and uses your current TZ setting to compute what the local time is. DST rules change from time to time, and both the operating system and the JDK need to be updated when this occurs.
Can you add the output of the following to your question:
# unix
date --rfc-2822; date +%s
# Java
System.out.println(new SimpleDateFormat("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z").format(new Date()));
System.out.println(new Date().getTime() / 1000);
The should both output something like:
Wed, 16 Sep 2009 17:26:08 +1000
1253085968

Categories