Why is my UTC instant not converting to BST? - java-time

I have the following code:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.UK);
Instant inst = DateTimeUtils.toInstant(sdf.parse("2019-08-13T18:00:00Z"));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm").withLocale(Locale.UK).withZone(ZoneId.of("Europe/London"));
System.out.println(formatter.format(inst));
//prints 18:00
This is surprising to me as I thought inst would be a GMT/UTC time and the formatter would format it to London time (which is BST (UTC+1:00) for this date), producing 19:00.
What am I missing here?
I'm guessing this is a generic issue with my code, but if it makes a difference this is using the org.threeten.bp.* classes from the ThreeTen-Backport project, further adapted for early Android in the ThreeTenABP project.

tl;dr
Instant // Represent a moment in UTC.
.parse( // Generate a `Instant` object from the content of text input.
"2019-08-13T18:00:00Z" // String in standard ISO 8601 format.
) // Returns a `Instant` object.
.atZone( // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone).
ZoneId.of( "Europe/London" ) // Specify a time zone using name in proper `Continent/Region` format. Never use 2-4 letter pseudo-zones such as `BST`.
) // Returns a `ZonedDateTime` object.
.toLocalTime() // Extract the time-of-day, without a date and without a time zone or offset. Returns a `LocalTime` object.
.format( // Generate text representing the content of this `LocalTime` object.
DateTimeFormatter
.ofLocalizedTime ( FormatStyle.SHORT ) // Automatically localize while generating a `String`.
.withLocale ( Locale.UK ) // Locale determines the human language and cultural norms to use in localizing.
) // Returns a `String` object.
19:00
Avoid legacy date-time classes
Your are mixing the terrible legacy classes (SimpleDateFormat, Date) with the modern java.time classes. Don’t do that. Use only java.time.
Instant = moment in UTC
Skip your first two lines of code. Your input string "2019-08-13T18:00:00Z" is in standard ISO 8601 format. These standard formats are used by default by the java.time classes when parsing/generating strings. So no need to specify a formatting pattern.
String input = "2019-08-13T18:00:00Z" ;
Instant instant = Instant.parse( input ) ;
instant.toString(): 2019-08-13T18:00:00Z
Instant is not flexible
I suspect your problem was in your attempt to format the value within a Instant. The Instant class is a basic building-block class within java.time. It merely represents a moment in UTC. It is not intended for things such as flexible generation of strings.
The more flexible classes are OffsetDateTime & ZonedDateTime classes.
ZonedDateTime
Apply a ZoneId to your Instant to adjust into a time zone, rendering a ZonedDateTime object.
ZoneId z = ZoneId.of( "Europe/London" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
zdt.toString(): 2019-08-13T19:00+01:00[Europe/London]
You seem to want to focus on the time-of-day alone. Extract a LocalTime object.
LocalTime lt = zdt.toLocalTime ();
lt.toString(): 19:00
For the London region in Daylight Saving Time (DST) on that date, the offset-from-UTC is one hour ahead. So we see the time-of-day is 7 PM versus the 6 PM of UTC.
Proper time zone
By the way BST is not a time zone. I suggest you avoid using these pseudo-zones.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as BST or EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
Use smart objects, not dumb strings
Your example code suggests you are too focused on strings. Use smart objects, not dumb strings.
Get your objects straight, using appropriate types. Generating strings should be the last step, a side-effort, akin to localization. Your business logic should be done by using proper objects, not by manipulating strings.
Localization
And speaking of localization:
Locale locale = Locale.UK;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime ( FormatStyle.MEDIUM ).withLocale ( locale );
String output = lt.format ( f );
19:00:00
Switch the locale to Locale.US for a different kind of result:
7:00:00 PM
All the code above was run in Java 13 early-access with the ThreeTen-Backport library per your needs stated in the Question.
import org.threeten.bp.* ;
import org.threeten.bp.format.* ;
Note to the reader: The ThreeTen-Backport library is further adapted for early Android in the ThreeTenABP library. See How to use ThreeTenABP in Android. If using Android 26 and later, the java.time classes are bundled, so you do not need the back-port at all.

Related

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));

Could not find the format for this date: "2018-09-09T09:04:47+00:00"

Getting Error
java.text.ParseException: Unparseable date: "2018-09-09T09:04:47+00:00"
Whatis the date format is this?
There seems to be some confusion, about this date format, so I will explain.
This is an ISO 8601 date-time value with a timezone offset.
References:
The ISO 8601 page in Wikipedia is accurate and pretty comprehensive.
The W3 Consortium have documented in a TR; here.
The Official version may be obtained from ISO; here.
The Z is an ISO standard timezone specifier. It means the same thing as +00.00, and is known in some circles (e.g. the military) as "Zulu time".
An ISO 8601 date/time does not "have to" end with a Z. There are other forms of timezone specification, and indeed a date/time does not need a timezone at all.
You should not need to trim it off the Z. Java's data-time parsers can parse the Z timezone specifier and give it its correct meaning ... if you use the right pattern.
If an ISO date time is "unparseable", that means that you have (explicitly or implicitly) used the wrong format to parse it.
Unfortunately, different countries (locales) have different default date / time formats, and worse still there is no reliable way (in general) to know which is the correct one to use ... if you don't know where it came from.
Fortunately ... ISO 8601 is an international standard. If you see a date / time that conforms to the ISO 8601 syntax, you know what it means.
There are a number of kinds of ISO 8601 date and date/time representation as explained in the W3 Consortium TR. The different kinds can be distinguished without any ambiguity.
If you are parsing using java.text.SimpleDateFormat, then the correct pattern for this variation of ISO 8601 is "yyyy-MM-dd'T'HH:mm:ssX". The pattern that works with java.time.format.DateTimeFormatter is also "yyyy-MM-dd'T'HH:mm:ssX"
The DateTimeFormatter class also defines a number of standard formats as constants. The format for this kind of ISO 8601 date/time is DateTimeFormatter.ISO_OFFSET_DATE_TIME. The other kinds are defined too.
The Date and Calendar classes and associated classes are legacy classes. It is advisable to use the new java.time classes instead in new code.
You should use 'X' for timezone:
String pattern = "yyyy-MM-dd'T'HH:mm:ssX";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
Date date = simpleDateFormat.parse("2018-09-09T09:04:47+00:00");
System.out.println(date);
Use this convert method to String to date which is ISO format. But in generaly ISO format ends with Z , but if not no problem. This method returns Date, and do it what ever u want from this return value.
public static Date toCalendar( String isoDate)
throws ParseException {
String s = isoDate.replace("Z", "+00:00");
try {
s = s.substring(0, 22) + s.substring(23); // to get rid of the ":"
} catch (IndexOutOfBoundsException e) {
throw new ParseException("Invalid length", 0);
}
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(s);
}
In Java8 TimeApi or later version has this usage,try it ;
OffsetDateTime offsetDateTime = OffsetDateTime.parse( "2018-09-09T09:04:47+01:00" );
Instant instant = offsetDateTime.toInstant();
java.util.Date date = java.util.Date.from( instant );
Or use only this pattern yyyy-MM-dd'T'HH:mm:ssX

How to convert local date to UTC in Mirth?

In Mirth I receive a local datetime string (201801011000) which I need to convert to UTC. I soon found out using the classic js new Date() doesn't work well.
This for example:
var d = new Date("2018-01-01 10:00");
logger.info(d.toString());
gives me an Invalid Date.
So after some more searching I found I can do this:
var d = DateUtil.getDate("yyyyMMddHHmm", "201801011000");
and from here I'm stuck. I don't know how I can convert this to UTC. Local server timezone is assumed which is enough for now, but in the future I also need to set a specific non-local timezone.
I tried to get the methods I can use with Object.getOwnPropertyNames(d), but that gives me the helpfull TypeError: Expected argument of type object, but instead had type object
I also tried looking up the java docs for DateUtil and tried some methods from that, but nothing worked.
Does anybody know how I can convert datestring from local time to UTC? All tips are welcome!
Ok, after messing around with this for about two full days I finally found a solution. In the end I had to tap into Java, but since I couldn't import any java dependencies I had to use their direct class path (e.g.: java.text.SimpleDateFormat).
In the end this is what worked for me:
var datestr = "201207011000".slice(0, 12); // This is just a datetime string to test with
var formatter_hl7 = new java.text.SimpleDateFormat("yyyyMMddHHmm");
formatter_hl7.setTimeZone(java.util.TimeZone.getTimeZone("CET"));
var formatter_utc = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm");
formatter_utc.setTimeZone(java.util.TimeZone.getTimeZone("UTC"));
var date_in_utc = formatter_utc.format(formatter_hl7.parse(date_str));
Regardless, I wish you all a beautiful day!
tl;dr
Do not use DateUtil whatever that is. (Perhaps Apache DateUtils library?)
Do not use terrible old date-time classes such as java.util.Date.
Use the modern industry-leading java.time classes.
Code for parsing a string lacking an offset, then assigning an offset of zero for UTC itself.
LocalDateTime // Represents a date and a time-of-day but without any concept of time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline.
.parse(
"201801011000" ,
DateTimeFormatter.ofPattern( "uuuuMMddHHmm" )
)
.atOffset( ZoneOffset.UTC ) // Assign an offset-from-UTC. Do this only if you are CERTAIN this offset was originally intended for this input but was unfortunately omitted from the text. Returns an `OffsetDateTime`.
.toInstant() // Extract an `Instant` from the `OffsetDateTime`. Basically the same thing. But `Instant` is always in UTC by definition, so this type is more appropriate if your intention is to work only in UTC. On the other hand, `Instant` is a basic class, and `OffsetDateTime` is more flexible such as various formatting patterns when generating `String` object to represent its value.
Using java.time
The modern approach in Java uses the java.time classes. This industry-leading framework supplanted the terribly troublesome old date-time classes such as Date, Calendar, and SimpleDateFormat.
DateTimeFormatter
Parse your input string. Define a formatting pattern to match.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMddHHmm" ) ;
String input = "201801011000" ;
LocalDateTime
Parse as a LocalDateTime because your input lacks an indicator for time zone or offset-from-UTC.
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
Lacking a zone or offset means this does not represent a moment, is not a point on the timeline. Instead, this represents potential moments along a range of about 26-27 hours, the range of time zones around the globe.
OffsetDateTime
If you know for certain that this date and time-of-day were intended to represent a moment in UTC, apply the constant ZoneOffset.UTC to get an OffsetDateTime object.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;
ZonedDateTime
Your Question is vague. It sounds like you might know of an specific time zone intended for this input. If so, assign a ZoneId to get a ZonedDateTime object.
Understand that an offset-from-UTC is but a mere number of hours, minutes, and seconds. Nothing more, nothing less. In contrast, a time zone is much more. A time zone is a history of past, present, and future changes to the offset used by the people of a certain region.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
Instant
A quick way to adjust back into UTC is to extract a Instant object. An Instant is always in UTC.
Instant instan = zdt.toInstant() ;
ISO 8601
Tip: Instead of using custom format for exchanging date-time values as text, use only the standard ISO 8601 formats. The standard formats are practical, easy to parse by machine, easy to read by humans across cultures.
The java.time classes use the ISO 8601 formats by default when parsing/generating strings. The ZonedDateTime::toString method wisely extends the standard to append the name of the zone in square brackets.
Instant instant = Instant.parse( "2018-07-23T16:18:54Z" ) ; // `Z` on the end means UTC, pronounced “Zulu”.
String output = instant.toString() ; // 2018-07-23T16:18:54Z
And always include the offset and time zone in your string. Omitting the offset/zone for a moment is like omitting the currency for a price: All you have left is an ambiguous number worth nothing. Actually, worse than nothing as it can cause all sorts of confusion and errors.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
In my project have function for convert datestring local time to UTC,
function getDateInUTC(dateString) {
return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm").setTimeZone(java.util.TimeZone.getTimeZone("UTC")).format(new java.text.SimpleDateFormat("yyyyMMddHHmm").setTimeZone(java.util.TimeZone.getTimeZone("CET")).parse(dateString));
}
Enjoy :)
You should use the latest classes java.time provided from Java8.
Steps are as follows:
Step-1. Parse String to LocalDateTime
Step-2. Convert LocalDateTime to the ZonedDateTime and then we can convert between different timezone.
Hope this help:
In Mirth you can write as:
String str = "201207011000";
var date_in_utc =java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
.format(java.time.ZonedDateTime.of(java.time.LocalDateTime
.parse(str,java.time.format.DateTimeFormatter
.ofPattern("yyyyMMddHHmm")),java.time.ZoneId.of("CET"))
.withZoneSameInstant(java.time.ZoneOffset.UTC));
Full Snippet:
ZoneId cet = ZoneId.of("CET");
String str = "201207011000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
LocalDateTime localtDateAndTime = LocalDateTime.parse(str, formatter);
ZonedDateTime dateAndTimeInCET = ZonedDateTime.of(localtDateAndTime, cet );
System.out.println("Current date and time in a CET timezone : " + dateAndTimeInCET);
ZonedDateTime utcDate = dateAndTimeInCET.withZoneSameInstant(ZoneOffset.UTC);
System.out.println("Current date and time in UTC : " + utcDate);
System.out.println("Current date and time in UTC : " + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").format(utcDate));
Give this a shout
var d = DateUtil.getDate("yyyyMMddHHmm", "201801011000");
var utcD = new Date(d).toISOString();
edit: Info on .toISOString() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString

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.