how to get and format date with timezone - java

I'am creating a date and store it into database, I want to get current time which is timezone = "Asia/Istanbul" not my local time.
I am creating the date in my local computer, my local timezone is also "Asia/Istanbul".
when i deploy it into my server, server timezone is utc, it is turning to utc everytime.
I have different 2 machine, 2 machines have different timezone so I need to set my data dates with the timezone.
here is what i have done. it is ok in my local computer, but fails on server which is UTC
LocalDateTime localDateTime = LocalDateTime.now();
// it gives my local date time, 2019-07-09T10:30:03.171
// local date is now 1:30 pm, UTC is 3 hours after, it looks ok.
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("Asia/Istanbul"));
//2019-07-09T10:30:03.171+03:00[Asia/Istanbul]
// it looks +3. I dont want to see +3, I want the date like 01:30 which is shiefted
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
zonedDateTime.format(formatter);
//2019-07-09T07:30:03.171Z
// zone is disappeared, this is 3 hours before UTC
I expect the date like Asia/Istanbul when i created it.

I wouldn’t use LocalDateTime at all. Use ZonedDateTime throughout to eliminate any and all doubt about the time. Also always pass a ZoneId (if not a Clock) to the now method. This makes your code independent of the time zone settings of the computer and JVM.
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Istanbul"));
System.out.println(zonedDateTime);
2019-07-09T14:14:17.280852+03:00[Asia/Istanbul]
You might have misunderstood the +03:00 part, people sometimes do. It means that the time shown is already 3 hours ahead of UTC. So the point in time shown is equal to 11:14:17 UTC.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(zonedDateTime.format(formatter));
2019-07-09 14:14:17
Your formatter does not include time zone, therefore it’s not shown. But it’s the time in İstanbul.
What went wrong in your code?
I am assuming that the comments in your code are from running on your server in UTC (it’s not perfectly clear) and that you ran the code around 10:30 UTC, the same as 13:30 in İstanbul.
A LocalDateTime is a date and time without time zone and without UTC offset. Its no-arg now method uses the JVM’s time zone setting, in this case UTC, so gives you 10:30 on the day in question. I think that ZonedDateTime.of is wrong here: it takes the 10:30 from the LocalDateTime and İstanbul time zone from the ZoneId object and gives you 10:30 in İstanbul, which is not what you wanted. You had wanted 13:30, AKA 1:30 PM.

Related

Error when I try to change my time/date to UTC-1

I have a Date with the actual time of my system (I live in Spain). I need to change it to UTC-1, but it doesn't matter if I write "UTC-1" or "UTC-2", it always gives me the same time less 2 hours, I mean:
My system hour (time_utc): 11:00 13/04/2021
Try UTC-1 (time): 09:00 13/04/21
Try UTC-2 (time): 09:00 13/04/21
I have this code:
Date time_utc = new Date();
DateFormat convertidor = new SimpleDateFormat("yyyy-MM-dd HH:00:00.000");
convertidor.setTimeZone(TimeZone.getTimeZone("UTC-1"));
time = convertidor.format(time_utc);
Why it doesn't work? Can anyone helps me? Thanks a lot!
¡Hola!
You can do that in a pretty short way using java.time (if you are allowed and willing to do so).
There are special classes that represent a moment in time in different time zones of offsets. One of them is an OffsetDateTime, see this example:
public class Main {
public static void main(String[] args) {
// create one of your example date times in UTC
OffsetDateTime utcOdt = OffsetDateTime.of(2021, 4, 13, 11, 0, 0, 0, ZoneOffset.UTC);
// and print it
System.out.println(utcOdt);
/*
* then create another OffsetDateTime
* representing the very same instant in a different offset
*/
OffsetDateTime utcPlusTwoOdt = utcOdt.withOffsetSameInstant(ZoneOffset.ofHours(2));
// and print it
System.out.println(utcPlusTwoOdt);
// do that again to see "the other side" of UTC (minus one hour)
OffsetDateTime utcMinusOneOdt = utcOdt.withOffsetSameInstant(ZoneOffset.ofHours(-1));
// and print that, too.
System.out.println(utcMinusOneOdt);
}
}
It outputs the following three lines:
2021-04-13T11:00Z
2021-04-13T13:00+02:00
2021-04-13T10:00-01:00
As you can see, the time of day is adjusted according to the offset.
The output could be formatted in your desired style if needed (this currently just uses the toString() method of OffsetDateTime).
UPDATE
You can achieve the output formatted as desired by defining the pattern as uuuu-MM-dd HH:mm when using a java.time.format.DateTimeFormatter.
Just add the following lines to the example above:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm");
System.out.println(utcOdt.format(dtf));
System.out.println(utcPlusTwoOdt.format(dtf));
System.out.println(utcMinusOneOdt.format(dtf));
This would then output
2021-04-13 11:00
2021-04-13 13:00
2021-04-13 10:00
And if you really want fix zeros for seconds and millis, then create your DateTimeFormatter like this:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:00.000");
which will cause output like this:
2021-04-13 11:00:00.000
2021-04-13 13:00:00.000
2021-04-13 10:00:00.000
As a supplement to the good answer by deHaar:
As Matt Johnson-Pint already asked, do you need to convert to a different time zone? This would be the most typical. If so, use that time zone, not just a UTC offset of -1. By all probability that time zone has used other offsets in the past and may well do so in the future. So -01:00 isn’t safe. A real time zone ID like Atlantic/Cape_Verde is safer.
You don’t need to go through the current time in your own time zone and convert. java.time can directly give you the current time in another time zone or at a specific UTC offset.
java.time can also truncate a time to whole hours.
So for example:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS");
ZoneId zone = ZoneId.of("Atlantic/Cape_Verde");
ZonedDateTime nowInCaboVerde = ZonedDateTime.now(zone);
System.out.println(nowInCaboVerde);
System.out.println(nowInCaboVerde.truncatedTo(ChronoUnit.HOURS)
.format(formatter));
Output:
2021-04-14T03:12:28.272010-01:00[Atlantic/Cape_Verde]
2021-04-14 03:00:00.000
PS Cabo Verde/Cape Verde was at offset -02:00 until 1975.
What went wrong in your code?
This is how confusingly the old TimeZone class behaves and one of the reasons why you should never use it: When given a time zone ID that it does not recognize, it returns GMT and pretends all is well. UTC-1 is not a recognized time zone ID. In case it didn’t make sense to refer to a real time zone and you needed the offset -01:00 from UTC, you might have used GMT-1 or GMT-01:00. Yes, TimeZone refers to UTC as GMT even though they are not strictly speaking the same.

How to convert UTC timezone to localtime zone using Joda-Time in Java? [duplicate]

DateTime dt = new DateTime("2014-09-15T21:20:14");
System.out.println(dt);
System.out.println(dt.plusMillis(581042272).toDateTime().toLocalDateTime().toDateTime(DateTimeZone.forID("GMT")));
the time in dt is in UTC, I want to set the time in dt plus milliseconds to GMT? However, the time is still printed as UTC (1 hour behind GMT). How can I set it so it's one hour in front?
2014-09-15T21:20:14.000+01:00
2014-09-22T14:44:16.272Z
I know the time is exactly one hour behind because I made this request at 15:44:16 GMT
Your DateTime is actually not in UTC - it's in the system default time zone. To fix it, you just need to tell it that the value you're passing in is in UTC:
DateTime dt = new DateTime("2014-09-15T21:20:14", DateTimeZone.UTC);
System.out.println(dt);
DateTime other = dt.plusMillis(581042272);
System.out.println(other);
Output:
2014-09-15T21:20:14.000Z
2014-09-22T14:44:16.272Z
Also note that you can't have made the request at 15:44:16 GMT, as that hasn't occurred yet. At the time I'm writing this, it's 16:05 British Summer Time, therefore 15:05 GMT. It's important to understand that the time zone in the UK isn't "GMT" - that's just the part of the time zone when we're not observing daylight savings.
If you want to convert to the UK time zone, you want:
DateTime other = dt.plusMillis(581042272)
.withZone(DateTimeZone.forID("Europe/London"));
For those that have trouble with converting datetime from a server to local datetime:
1.Make sure the server gives you a UTC time, meaning, the format should contain a timezone.
2.Convert with pattern, if the api does not give you an timezone, then you might get an exception because of the last 'Z'.
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
DateTime dt = formatter.parseDateTime(currentPost.postDate);
3.to check the time offset (optional)
DateTimeZone ActualZone = dt.getZone();
4.Convert to local time
TimeZone tz2 = TimeZone.getDefault();
DateTime localdt = new DateTime(dt, DateTimeZone.forID(tz2.getID()));
(if you control the API yourself, and it happens to be an asp.net api, check this, to set the Kind of the datetime, even though you might have saved it as UTC time in the database, you will send the datetime with the default server timezone)
val marketCentreTime = timeInAnotherTimezone.withZone(DateTimeZone.forID("yourCountryName/andyourCityName"));

Time format ends up changing in production

I have the following code which gets current time in a certain format. This works perfectly fine locally when I test it out on my laptop.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS z");
ZonedDateTime date = ZonedDateTime.now();
String timeStamp = formatter.format(date);
This above works locally and the timestamp value is in following format:
2020-02-24 05:23:20.675 MST
But when I push it to production, the format changes to following:
2020-02-24 05:23:20.675 -07:00
I do not have access to the production settings and the team that handles it is in another timezone and will not be able to get them now. Believe it is some setting on their end but is there something I could do such that the format is always like: 2020-02-24 05:23:20.675 MST ?
Please advice, thanks.
You have to specify your time zone, it seems in production you are using a different time zone than the one in local. Beside in your code you don't specify any Zone, for that it took the default Zone.
To solve this, you have to specify the zone :
ZoneId zoneId = ZoneId.of("America/Dawson_Creek"); // specify the zone you want to use
ZonedDateTime date = ZonedDateTime.now(zoneId);

Date from ZonedDateTime instant not in utc

I am creating date like this:
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
Date.from(now.toInstant());
I need Date object have current time in utc, but when I print date it gives me my local time and not utc time.
I also tried with:
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
Date date = Date.from(now.toInstant());
But when I print Date again time is not in utc. Am I doing something wrong when creating Date object. Why above 2 approaches not give me Date that have current time in utc.
Two points:
Avoid the long outdated Date class, in particular when you are already using classes from java.time, the modern Java date and time API.
A Date object hasn’t got and cannot have a time zone in it.
To print offset or time zone
If you need your offset, you need to hold on to your OffsetDateTime (or ZonedDateTime) object:
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println(now);
On my computer this just printed
2017-11-21T11:53:11.519Z
The Z in the end indicates Zulu time zone, another name for UTC (you may also informally think of it as Zero offset from UTC).
If you would like a more human-readable format, you are right, use a formatter:
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println(now.format(formatter));
Depending on your locale and the time, this prints something like
Tuesday, November 21, 2017 11:53:11 AM Z
Again the Z means Zulu time zone, UTC.
Date is not going to help you
A Date is just a point in time. So is the Instant that you use for initializing the date. None of them has got a time zone or offset. The difference here is their toString methods: The Instant is always printed in UTC, the Date usually (always?) in the JVM’s default time zone. The latter confuses many into thinking the Date has a time zone when it hasn’t. See All about java.util.Date.
As I have demonstrated, a formatter may put a time zone or offset into a string when formatting the date-time. This does not in any way modify the date-time object, whether OffsetDateTime, ZonedDateTime, Instant or Date. The long outdated DateFormat class may do the same when formatting a Date. It cannot and will not set a time zone in the Date object since (and I repeat) a Date object cannot have a time zone in it.
Long story short, you have no need for the outdated Date class that I can see.

Convert database time to IST datetime

I have a time value stored in my database in HH:mm:ss format (using MySQL's time type). This time is to be considered as a value of IST timezone. The server on which my Java code runs follows the UTC timezone.
How can I get a formatted datetime in yyyy-MM-dd HH:mm:ss in IST (or in UTC millis)? Following is what I've tried till now:
// ... Code truncated for brevity
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalTime time = resultSet.getTime("send_time").toLocalTime();
LocalDateTime datetime = time.atDate(LocalDate.now());
System.out.println(datetime.format(formatter));
The above correctly prints the datetime on my local machine, which is on IST, but I'm concerned about how it will behave on the remote server.
Your approach is fine and should work regardless of your computer's time zone since there is no time zone information in either LocalTime or LocalDateTime. One possible issue is with LocalDate.now() which returns today's date in the computer's local time zone, not in IST. You may want to replace it with LocalDate.now(ZoneId.of("Asia/Calcutta")).
Or as commented by #OleV.V. you could use the new driver facilities to derive a LocalTime directly:
LocalTime time = resultSet.getObject("send_time", LocalTime.class);
Note possible caveats with your approach:
if the time zone you use introduces DST, you may end up with two identical times in your DB that were actually different instants - using UTC to store times is probably more robust
time in mysql can store values smaller than 00:00 and larger than 23:59:59.999999, in which case you may experience unexpected behaviours on the Java side.

Categories

Resources