Converting date long value to current Timezone value - java

I have a date as long value, I want to display the Date format in words depends upon the country time zone. Please help me in converting this.

Take a look at the java.text.DateFormat class. It provides several option how to output the current Data and Time.
For example the following code prints the current date and time in the long format option for the en_UK locale:
DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.UK).format(new Date());
Prints:
23 January 2012 08:17:36 CET
To display any date, just pass the long value to the constructor of the Date object.
DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.UK).format(new Date(<your long value here>));

I have a date as long value
You need to understand date as long value is the absolute value (UTC) of time in milli seconds since Epoch i.e. '1st Jan 1970 00:00:00'. This value has no timezone information embedded in it. Now if you want to display this time in your current local timezone then simply do this:
Date dt = new Date(1327303085000l);
System.out.printf("Date: %s%n", dt);
It prints:
Date: Mon Jan 23 02:18:05 EST 2012
Note the when it prints the date it automatically prints it with my current timezone.
However if you want customized formattng to display your date then you can take a look at the DateFormat class in Java.

Related

Java convert RFC 1123 datetime to milliseconds from epoch

I'm trying to convert a date in RFC 1123 format to number of milliseconds from epoch in Java.
My usecase is that I've uploaded a file to my pCloud storage (directly from my browser) and then from java, request the REST API to retrieve the last modified datetime of this file.
The string I've received is "Fri, 08 Apr 2022 15:57:48 +0000".
But from my computer, the file last modification is at 17:57:48.
But I'm in Europe/Paris, so that I'm at timezone offset +2.
I tried to do:
String modified = "Fri, 08 Apr 2022 15:57:48 +0000";
DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME;
LocalDateTime localDateTime = LocalDateTime.parse(modified, formatter);
ZonedDateTime zdt = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
At this point, if I output variables:
System.out.println(localDateTime);
System.out.println(zdt);
It displayed:
2022-04-08T15:57:48
2022-04-08T15:57:48+02:00[Europe/Paris]
Now to convert to milliseconds from epoch time, I've tried:
localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
zdt.toInstant().toEpochMilli();
localDateTime.toInstant(OffsetDateTime.now().getOffset()).toEpochMilli();
And all these give
1649426268000
And if I use the following formatter :
new SimpleDateFormat("YYYY/MM/dd HH:mm:ss").format(long milliseconds).
It display:
2022/04/08 15:57:48
So it missing my timezone offset?! (the "+02:00[Europe/Paris]").
I found this solution:
TimeZone tz = TimeZone.getTimeZone(ZoneId.systemDefault());
long milli = zdt.toInstant().toEpochMilli() + tz.getOffset(new Date().getTime())
And formmating milli as just before with the same SimpleDateFormat, I have:
2022/04/08 17:57:48
which is the correct value.
Is there a cleaner way to have the correct long millisecond to epoch from my string date in RFC 1123 format?
Especially I think in my solution I have to do something like
tz.getOffset(extact date from "modified" string)
because the offset is not the same according to DST (summer or winter), and I hope this use case must be natively managed with all the Class of Java ?
You are using a LocalDateTime, which stores only date and time components. Then you proceed to apply the local time zone. Your local time zone is not relevant to this task, so should not be used.
Instead, since your input contains a date, time, and offset, you should parse to an OffsetDateTime.
String modified = "Fri, 08 Apr 2022 15:57:48 +0000";
DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME;
OffsetDateTime odt = OffsetDateTime.parse(modified, formatter);
Then you can use either of the following to get milliseconds since the epoch:
odt.toInstant().toEpochMilli()
or
odt.toEpochSecond() * 1000
Either will give you the correct value of 1649433468000. See similar code run live at IdeOne.com.
(Note, there is no toEpochMilli method directly on an OffsetDateTime, so either go through an Instant first, or get seconds and multiply by 1000.)

Convert a GMT datetime to local timezone datetime

In Java 8 I need a way to get the local datetime (GMT+1) from a GMT datetime in ISO 8601 format.
A simple example:
Client sends me (Server) this datetime "2020-01-11T23:00:00.000Z"
Client sends me this when the user choose the 12 Jan 2020 from the datepicker. Is the 12 Jan for GMT+1 but the day before for GMT.
For the reason above then I know that for me this datetime is not the 11 Jan 2020 but 12 Jan 2020 in GMT+1.
So I need this value "2020-01-12T00:00:00.000"
To be precise I don't need to print this with simpleDateFormat but just covert "2020-01-11T23:00:00.000Z" to "2020-01-12T00:00:00.000" in a java.util.Date class field
Thanks.
The problem is that the source system took the pure date value, but added time at midnight, then converted that to UTC, but you want the pure date value in a java.util.Date, which by default prints in your local time zone, i.e. the JVM's default time zone.
So, you have to parse the string, revert the value back to the time zone of the source system, the treat that local time as a time in your own JVM's default time zone.
You can do that like this, showing all the intermediate types:
String sourceStr = "2020-01-11T23:00:00.000Z";
ZoneId sourceTimeZone = ZoneOffset.ofHours(1); // Use real zone of source, e.g. ZoneId.of("Europe/Paris");
// Parse Zulu date string as zoned date/time in source time zone
Instant sourceInstant = Instant.parse(sourceStr);
ZonedDateTime sourceZoned = sourceInstant.atZone(sourceTimeZone);
// Convert to util.Date in local time zone
ZonedDateTime localZoned = sourceZoned.withZoneSameLocal(ZoneId.systemDefault());
Instant localInstant = localZoned.toInstant();
Date localDate = Date.from(localInstant); // <== This is your desired result
// Print value in ISO 8601 format
String localStr = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").format(localDate);
System.out.println(localStr);
Output
2020-01-12T00:00:00.000
The code can of course be merged together:
String input = "2020-01-11T23:00:00.000Z";
Date date = Date.from(Instant.parse(input).atZone(ZoneOffset.ofHours(1))
.withZoneSameLocal(ZoneId.systemDefault()).toInstant());
System.out.println(date);
Output
Sun Jan 12 00:00:00 EST 2020
As you can see, the date value is correct, even though I'm in the US Eastern time zone.

Converting java.util.Date to java.sql.Timestamp results into wrong value

Server side code (server timezone is UTC):-
Date aDate = new Date();
java.sql.Timestamp aTimestamp = new java.sql.Timestamp(aDate.getTime());
Client side (Mobile app, timezone GMT +5:30):-
Hitting a service request which runs above code on server side
The issue is when i debugged on server, found following values :-
aDate.getTime() prints to -> 1470472883877 milliseconds i.e., Sat Aug 06 2016 14:11:23 GMT+0530
but
aTimestamp prints to -> (java.sql.Timestamp) 2016-08-06 08:41:44.109
It's kinda weird, i've no idea what's going on in conversion !! please help
UTC and GMT are formats.
java.util.Date and java.sql.Timestamp are independent of the timezone. They store a long time in ms for representing their inner state.
For information, Calendar is timezone aware.
So with Date or Timestamp, to differentiate GMT or UTC format in an output, you have to use a formater which outputs the date into string by being aware the timezone.
In your output : 2016-08-06 08:41:44.109, you don't use a formater which is aware of the timezone. It's probably the result of a toString() on the java.sql.Timestamp instance or something of similar.
What you consider as a conversion is not a conversion but a formatting since the timestamp stays the same between the two objects.
If you want to display in the UTC format, use the appropriate formater with a
SimpleDateFormat for example :
SimpleDateFormat dt= new SimpleDateFormat("MM/dd/yyyy hh:mm:ss z");
dt.setTimeZone(TimeZone.getTimeZone("UTC"));
String dateStringInUTC = dt.format(new Date(yourSqlTimestamp.getTime()));
The following is probably what you are looking for:
Calendar cal = Calendar.getInstance(Locale.GERMANY); // use your locale here
Timestamp aTimestamp = new Timestamp(cal.getTimeInMillis());
System.out.println(aTimestamp);
System.out.println(cal.getTime());
And the output:
2016-08-06 19:12:54.613
Sat Aug 06 19:12:54 CEST 2016

Calendar.getTime() not returning UTC date if TimeZone is defined

I have done this for my Calendar instance to return Date in UTC timezone:
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:SS Z");
TimeZone tz = TimeZoneUtil.getTimeZone(StringPool.UTC);
formatter.setTimeZone(tz);
Date dtStart = null;
Date dtEnd = null;
try{
dtStart = formatter.parse(formatter.format(startDate.getTime()));
dtEnd = formatter.parse(formatter.format(endDate.getTime()));
}catch (Exception e) {
e.getStackTrace();
}
It works fine till I format calendar timestamp to return a string date with required timezone but when I parse that string date to Date date, it again picks up local timezone?
I need to store Date object in UTC timezone.
Any help will be highly appreciated!
You can use this:
Date localTime = new Date();
//creating DateFormat for converting time from local timezone to GMT
DateFormat converter = new SimpleDateFormat("dd/MM/yyyy:HH:mm:ss");
//getting GMT timezone, you can get any timezone e.g. UTC
converter.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("local time : " + localTime);;
System.out.println("time in GMT : " + converter.format(localTime));
It will give:
local time: Fri Jun 21 11:55:00 UTC 2013
time in GMT : 21/06/2013:11:55:00
I hope it will help.
Cheers.
Date object in java will always store the values in the host machine (your system) time zone information.
This is from javadoc :
Although the Date class is intended to reflect coordinated universal time (UTC), it may not do so exactly, depending on the host environment of the Java Virtual Machine.
You should trying using Joda Time which is much advanced.
Instead of setting TimeZone in multiple places, it is a good idea to set timezone using -Duser.timezone=GMT or PST.
And, you can easily test how Java deals with timezone and getTime() ignores timezone with an actual example:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); // print with timezone
TimeZone timeZone = TimeZone.getTimeZone(ZoneId.of("GMT"));
TimeZone.setDefault(timeZone); // set system timezone as GMT
sdf.setTimeZone(timeZone); // formatter also has a timezone
Date date = new Date();
System.out.println(date); // system says GMT date
System.out.println(date.getTime()); // only prints time in milliseconds after January 1, 1970 00:00:00 GMT
System.out.println(sdf.format(date));
timeZone = TimeZone.getTimeZone(ZoneId.of("America/Los_Angeles"));
TimeZone.setDefault(timeZone); // set system timezone as GMT
sdf.setTimeZone(timeZone); // formatter also has a timezone
date = new Date();
System.out.println(date);
System.out.println(date.getTime()); // prints the same value as above, "not including timezone offset"
System.out.println(sdf.format(date));
// GMT and PDT times are same as getTime() only returns time in ms since UTC for the day ignoring timezone which is mostly used for formatting
Wed Mar 14 22:43:43 GMT 2018
1521067423108
2018-03-14T22:43:43+0000
Wed Mar 14 15:43:43 PDT 2018
1521067423125 // not includes timezone in getTime()
2018-03-14T15:43:43-0700 // formatting looks fine
The good explanation of why Date object taking Current time zone value ,
please refer this SO answer
EDIT.
here I am gonna add some important part of that answers.
java.util.Date is has no specific time zone, although its value is most commonly thought of in relation to UTC. What makes you think it's in local time?
To be precise: the value within a java.util.Date is the number of milliseconds since the Unix epoch, which occurred at midnight January 1st 1970, UTC. The same epoch could also be described in other time zones, but the traditional description is in terms of UTC. As it's a number of milliseconds since a fixed epoch, the value within java.util.Date is the same around the world at any particular instant, regardless of local time zone.

Database datetime to java.util.Date conversion with timezone

I have a task of converting, time stored on one of my DB(Sql Server)'s table's column to a specified timezone. The column always contains time in UTC timezone.
The problem I am facing is, when hibernate READS the column and sets it to my entity class, it sets the time in the application server's timezone.
For Eg:
if DB has value - 07 Jul 2012 10:30 (which is actually UTC), the hibernate sets the mapped date field as 07 Jul 2012 10:30 PST (assuming the JVM is running at PST).
Now if this date gets converted to any other timezone.. say GMT+5:30, i get unexpected result
To fix the above issue... i wrote the following code
//Reading the DB time (which does not have timezone info)
Date dbDate = entityObj.getDBUtcDate();
//Setting GMT timezone to the date, without modifying the date
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
c.set(dbDate.getYear(), dbDate.getMonth(), dbDate.getDate()..., dbDate.getMinutes());
Date utcDate = c.getTime();
Using above code.. I could get the DB stored date back in UTC timezone, but when I did conversion to some other timezone(say GMT+5:30) using below logic
Calendar outCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+5:30"));
outCal.setTimeInMillis(utcDate.getTime());
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, outCal.get(Calendar.YEAR));
cal.set(Calendar.MONTH, outCal.get(Calendar.MONTH));
cal.set(Calendar.DAY_OF_MONTH, outCal.get(Calendar.DAY_OF_MONTH));
cal.set(Calendar.HOUR_OF_DAY, outCal.get(Calendar.HOUR_OF_DAY));
cal.set(Calendar.MINUTE, outCal.get(Calendar.MINUTE));
cal.set(Calendar.SECOND, outCal.get(Calendar.SECOND));
cal.set(Calendar.MILLISECOND, outCal.get(Calendar.MILLISECOND));
//Converted date
Date pstTime = cal.getTime();
//Converted time mill seconds
long timeMilSec = pstTime.getTime();
The time millisecond of the converted date started coming as negative (-54672...), which seems to be representing an invalid time.
My question here is
How can i restore the timezone information from DB (without having to have any extra column in DB to specifically store timezone information)?
OR
How can i convert a DB time into a time having a specified timezone(UTC)?
PS: I expect the output in the form of java.util.Date/ Calendar because i need to do one more conversion on this date
Please help me resolving this issue
Dates in Java don't have a time zone. They're just a universal instant in time. If you want to display the date in a given time zone, then simply use a DateFormat initialized with this time zone:
DateFormat df = DateFormat.getInstance();
df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("The date in the database, in the UTC time zone, is "
+ df.format(date));
You don't need to convert anything. The date format prints the appropriate values based on the universal instant it formats, and the time zone you tell it to use.
Similarly, if you want to know if the date is a monday or a tuesday, or if it's 1 o'clock or 2 o'clock, you need to first choose a time zone, convert it to Calendar, and ask the calendar for the information:
Calendar cal = Calendar.getInstance(someTimeZone);
cal.setTime(date);
System.out.println("The day for the date stored in the database, for the time zone "
+ someTimeZone
+ " is " + cal.get(Calendar.DATE));
Side note: don't use deprecated methods. They're deprecated for good reasons.

Categories