Material date-time pickers and zoned time string problem - datepicker

I have a page with #material-ui/pickers
<TimePicker .. value={value}/> /* value == 2020-12-24T13:05:10.714Z */
The value in the example is a zoned datetime string coming the from server.
My time zone is +2:00, Ukraine/Kiev.
The problem is that rendered time is 15:05. Is this behaviour normal when input value is zoned datetime?
I would like to see 13:05. Is this the server that provides me with incorrect datetime format or is it me misusing #meterial/pickers and #date-fns ?

2020-12-24T13:05:10.714Z is an ISO-8601 datetime string. The suffix Z means that the time is in UTC (see wikipedia). The rendered time of 15:05 in your +02:00 zone matches that.
So yes, if your server meant to specify 13:05 Kiev time, it's using the wrong format or the wrong time. It should say 2020-12-24T11:05:10.714Z or 2020-12-24T13:05:10.714+02:00.

Related

Google Calendar api ignores timezone

Im using the CalendarApi in flutter and in order to get events I use the list method like that:
calendarApi.events.list(
cls.calendarId,
timeZone: <specific timezone>
timeMin: DateTime.now().today().toUtc(),
timeMax: DateTime.now().tomorrow().toUtc(),
),
No matter what timezone I tried it always return the event start and end date in UTC format.
I tried using the timezones in multiple formats:
America/Los_Angeles
UTC - 08:00
GMT format
Pacific Standard Time
None of the following worked.
In addition in the in google calendar's settings the timezone is set correctly.
From the documentation:
Must be an RFC3339 timestamp with mandatory time zone offset, for example, 2011-06-03T10:00:00-07:00, 2011-06-03T10:00:00Z. Milliseconds may be provided but are ignored. If timeMax is set, timeMin must be smaller than timeMax.
Make sure the strings you are sending follow one of these pattens:
YYYY-MM-DDTHH:MM:SS±HH:MM
or
YYYY-MM-DDTHH:MM:SSZ
So for example, the time that this answer was posted would be:
2021-07-27T16:08:02+02:00
or:
2021-07-27T14:08:02Z
Where the Z signifies 'Zulu', or UTC.

ZonedDateTime value incorrect after loading via Spring Boot JPA, PostgreSQL

I have a ZonedDateTime with a specific instant in time, with the Zone set to America/Los_Angeles.
If I display this using the pattern "d-MMM-uuuu HH:mm VV" it shows as I expect (e.g. ... 8:00 am America/Los_Angeles).
However, if I change the pattern very minimally by removing the "VV", then it does not show the time in west coast time, it shows it in my local time (east coast), or 11:00 am - so it essentially ignores the zone set on the ZonedDateTime and instead uses something else (I assume the system local zone).
I would prefer to not display the time zone id in some cases, to save space (in a table for instance), but still want it to be displayed in the local time.
Is there a way to do that?
Update:
I note that using the pattern "d-MMM-uuuu HH:mm O", surprisingly, gives what I consider a wrong answer:
2-Jun-2020 11:09 GMT-7
here is the correct time, which shows using VV:
2-Jun-2020 08:09 America/Los_Angeles
The 11am value with "GMT-7" looks like it is clearly a bug - granted I am still using Java 8.
Update:
I think the problem may be in the data layer, though I am still trying to figure that out... (I am using Spring Boot JPA and PostgreSQL).
If I just purely use Java, as such:
ZoneId pdt = ZoneId.of("America/Los_Angeles");
ZonedDateTime now = ZonedDateTime.now().withZoneSameInstant(pdt);
logger.debug("now with VV: "+now.format(DateTimeFormatter.ofPattern("d-MMM-uuuu HH:mm VV")));
logger.debug("now with O: "+now.format(DateTimeFormatter.ofPattern("d-MMM-uuuu HH:mm O")));
logger.debug("now with nothing: "+now.format(DateTimeFormatter.ofPattern("d-MMM-uuuu HH:mm")));
logger.debug("now with VV+withZ: "+now.format(DateTimeFormatter.ofPattern("d-MMM-uuuu HH:mm VV").withZone(pdt)));
logger.debug("now with O+withZ: "+now.format(DateTimeFormatter.ofPattern("d-MMM-uuuu HH:mm O").withZone(pdt)));
logger.debug("now with nothing+withZ: "+now.format(DateTimeFormatter.ofPattern("d-MMM-uuuu HH:mm").withZone(pdt)));
logger.debug("using static formatter: "+now.format(TIMESTAMP_FORMATTER_SHORT));
logger.debug("using static formatter w/zone: "+now.format(TIMESTAMP_FORMATTER_SHORT.withZone(pdt)));
then in every case it shows the expected correct time in LA.
So, in debugging to see the differences, I see this anomaly:
In plain java if I look at the value of now (in code above), it looks correct - the LocalDateTime shows the current time in LA, and the offset is 7 hrs.
If I look at the ZonedDateTime value that is set after the JPA load, however, it looks unusual:
the value stored in the DB has the hour at 15 (as expected, UTC time)
the value in the LocalDateTime within the ZonedDateTime is off - it is showing the hour as 11, which is the local system time, not the time in LA
however the ZonedDateTime offset is still -7
What is really odd about this is that somehow DateTimeFormatter corrects the problem, but only when I use VV in the format.
I have determined the problem (not with JPA or PostgreSQL unsurprisingly).
Rather this is a bug that had been introduced a long time ago, but never exposed until I switched to trying to show a shorter display of the timestamp.
The code actually causing the problem was post processing a native query, incorrectly converting a java.sql.Timestamp into a ZonedDateTime. Here is the problem code:
java.sql.Timestamp timestamp = (Timestamp) objects[0];
String tzId = (String) objects[1];
ZonedDateTime dt = ZonedDateTime.of(timestamp.toLocalDateTime(), ZoneId.of(tzId));
I was incorrectly assuming that the ZonedDateTime.of would use the provided ZoneId to revise the time, but I believe that is not how it works. Instead, the toLocalDateTime() was creating a LocalDateTime based on the system default, which therefore did not agree with the ZoneId value passed in, which was the value stored in the DB and not the same as the system default.
Here is how I corrected the code:
java.sql.Timestamp timestamp = (Timestamp) objects[0];
String tzId = (String) objects[1];
ZonedDateTime dt = ZonedDateTime.of(timestamp.toLocalDateTime(), ZoneId.systemDefault())
.withZoneSameInstant(ZoneId.of(tzId));

Compare String time to Local Server Time

Have a string object with a specific format of date.
Need to check if that dateStr is after the current time on local machine.
Having trouble with conversions and LocalDateTime
String dateStr = "Oct 27 2017 02:29:00 GMT+0000";
public static final String DATE_FORMAT = "MMM dd yyyy HH:mm:ss zzzZ";
I know something is fishy in the below code with the usage of LocalDateTime
public static boolean isFutureDate(String dateStr){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
LocalDateTime dateTime = LocalDateTime.parse(dateStr, formatter);
return(dateTime.isAfter(LocalDateTime.now()));
}
Trouble is with timezones and date conversions.
Please help find the right way of checking if a dateStr is after the current local date this in Java 8?
Local… types have no time zone
You are using the wrong type for your data.
The Local… types including LocalDateTime purposely have no concept of time zone or offset-from UTC. As such they not represent a moment on the time line, only rough idea of a range of possible moments. Use LocalDateTime only when the time zone is unknown or irrelevant; never use it for an actual moment in history.
Use OffsetDateDate for values with an offset-from-UTC, a number of hours and minutes.
Use ZonedDateTime for values with an assigned time zone. A time zone such as Asia/Kolkata or America/Montreal is a particular region’s history of past, present, and future changes to its offset-from-UTC. Anomalies such as Daylight Saving Time (DST) mean a change to the offset.
If you know all your inputs are in GMT/UTC, use OffsetDateTime. If the inputs may use time zones, parse as ZonedDateTime objects.
This input data format is terrible. If you have any control, use standard ISO 8601 formats instead when exchanging date-time values as text.
All this has been covered many times already on Stack Exchange. Please search more thoroughly before posting. And search Stack Overflow to learn more. I kept my Answer here brief, as this is a duplicate.
When parsing to a LocalDateTime, you're ignoring the offset (+0000), and I'm not sure if that's what you really want.
In this case, the +0000 offset means the date/time is October 27th 2017 at 02:29 AM in UTC. When you parse to a LocalDateTime, you're ignoring the offset (so it represents only "October 27th 2017 at 02:29 AM", not attached to any timezone) and comparing to your local date/time (or the current date/time in the JVM's default timezone).
If you want to make a comparison that also considers the offset, you can parse it to OffsetDateTime and convert to Instant to compare it with the actual UTC instant, regardless of the timezone.
Also, the month name is in English (I'm assuming it's English, but you can change this accordingly), so you must a java.util.Locale in the formatter (if you don't set a locale, it'll use the JVM default, and it's not guaranteed to always be English):
// parse to OffsetDateTime (use the same formatter)
String dateStr = "Oct 27 2017 02:29:00 GMT+0000";
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm:ss zzzZ", Locale.US);
OffsetDateTime odt = OffsetDateTime.parse(dateStr, fmt);
// compare Instant's
System.out.println(odt.toInstant().isAfter(Instant.now()));
Although it works for you now, keep in mind that the default locale can be changed without notice, even at runtime. If your input has locale-sensitive date (such as month names), it's better to specify it as above.

Is this a valid time?

I get the following datetime String from a backend system: 2014-06-10+02:00.
Is this a valid datetime? There is no information about the time (I get only the date) but there is a time offset.
If it is valid according to which standard is this valid and what is the UTC time?
Thanks a lot
This is a valid date, not a date-time.
An offset-from-UTC is relevant to a date. For any given moment the date varies around the globe by time zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
By the way, an offset-from-UTC is not a time zone. A time zone is a history of changes (past, present, and future) to the offset used by a particular region. A time zone has a name in format of continent/region such as America/Montreal.
With a date and an offset, you can determine the range of all moments occurring in that day, all the points on the timeline.
Example code in Java.
ZoneOffset offset = ZoneOffset.parse( "+02:00" );
LocalDate ld = LocalDate.parse( "2014-06-10" ) ;
OffsetDateTime odt = OffsetDateTime.of( ld , LocalTime.MIN , offset );
https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
The output is valid Date but not a valid Time as per ISO Date Specification. Please see ISO_OFFSET_DATE.
UTC (Coordinated Universal Time) is a time standard is defined by International Telecommunications Union.
If it is valid according to which standard is this valid and what is
the UTC time?
You have asked three questions in this line and the answer to these questions are as follows:
Is it valid?
Yes, it is a valid date string.
You have already mentioned in your question that it does not have a time part; rather, it has a (timezone) offset of +02:00 hours. So, it is just a valid date string, not a date-time string.
Which standard is this?
This is ISO 8601.
What is the UTC time?
A date starts with the start-of-the-day time which, in most cases, is 00:00 hours. However, for the timezones that observe DST, it may not be the case. Such timezones have generally one hour difference in the timezone offset between with and without DST.
Your string has a fixed (timezone) offset (+02:00); rather than a timezone itself (e.g. Africa/Cairo) and therefore, in this case, the start of the day is always 00:00 hours.
So, it can be written as 2014-06-10'T'00:00:00+02:00. As soon as you represent it in this way, I am sure you must have already guessed that it is equivalent to 2014-06-09'T'22:00:00Z where Z is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).
Enough talking, let's write some code.
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String str = "2014-06-10+02:00";
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendPattern("u-M-d['T'[H[:m[:s]]]]XXX")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.toFormatter(Locale.ENGLISH);
OffsetDateTime odt = OffsetDateTime.parse(str, dtf);
System.out.println(odt);
OffsetDateTime odtUtc = odt.withOffsetSameInstant(ZoneOffset.UTC);
// The default format omits second and fraction-of-second if they are zero
System.out.println(odtUtc);
// Custom format
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
System.out.println(formatter.format(odtUtc));
}
}
Output:
2014-06-10T00:00+02:00
2014-06-09T22:00Z
2014-06-09T22:00:00Z
Learn more about the the modern date-time API* from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
yes it is correct date format.There are lot of place jerusalam..etc with the +2 hour you can find it in your system.

Displaying the timezone properly in XSLT

Was using the below tag for displaying the timezone which was working fine until now when the daylight saving has happened and as our server is in UK displaying the time as 01/04/2015 03:43:00 PM + 0100, we would also like to have the timezone displayed, please advice.
Tag Used Previously:
date:format-date(date:date-time(), 'dd/MM/yyyy hh:mm:ss a Z')
Regards
Arvind
If by "properly" you mean you want it displayed as "BST" (for British Summer Time) then there isn't actually enough information in the date/time value to do this - a time-zone offset of +1 occurs in many different timezones near the Greenwich meridian.
You're using the EXSLT library for formatting dates and times. This is based on Java's SimpleDateFormat class, so you could try your luck with the timezone designator z instead of Z.
Alternatively, if you've got access to XSLT 2.0, you can use the format-dateTime() function. This suffers from the same problem (the dateTime value only stores an offset, which doesn't actually tell you the name of the timezone). But you can give the processor a clue by setting the 5th argument of format-dateTime() to "Europe/London", in which case it might be able to work it out.