How to find equality of hr, min in date - java

I need to find equality of hour, minutes in date (1 date in DST, 1 date after DST) in java. Both dates are in UTC. DST ends in UK 2020-10-26 2 AM, so in above example, hour and minute are equal.
Date1 = 2020-10-22T07:00:00+0000
Date2 = 2020-10-26T08:00:00+0000

ZoneId zoneUk = ZoneId.of("Europe/London");
ZonedDateTime a = ZonedDateTime.parse("2020-10-22T07:00:00+00:00").withZoneSameInstant(zoneUk);
ZonedDateTime b = ZonedDateTime.parse("2020-10-26T08:00:00+00:00").withZoneSameInstant(zoneUk);
Notice the additional : in the time offset or it can't be parsed.
System.out.println(a); // 2020-10-22T08:00+01:00[Europe/London]
System.out.println(b); // 2020-10-26T08:00Z[Europe/London]
System.out.println(a.toLocalTime()); // 08:00
System.out.println(b.toLocalTime()); // 08:00
System.out.println(a.toLocalTime().equals(b.toLocalTime())); // true

Your date-time strings have Zone-Offset of +0000 and therefore parsing them into OffsetDateTime (using an appropriate DateTimeFormatter) will be a more natural choice. Once you have parsed them into OffsetDateTime, convert them to the ZonedDateTime corresponding to the time-zone of the UK. As a final step, you need to get the local time part of the ZonedDateTime.
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// The given date-time strings
String strDate1 = "2020-10-22T07:00:00+0000";
String strDate2 = "2020-10-26T08:00:00+0000";
// Define the formatter for the given date-time strings
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("u-M-d'T'H:m:sZ");
// ZoneId of the UK
ZoneId tzLondon = ZoneId.of("Europe/London");
// Get the corresponding date-time in the UK
ZonedDateTime zdt1 = OffsetDateTime.parse(strDate1, formatter).atZoneSameInstant(tzLondon);
ZonedDateTime zdt2 = OffsetDateTime.parse(strDate2, formatter).atZoneSameInstant(tzLondon);
System.out.println(zdt1);
System.out.println(zdt2);
// Get local date from ZonedDateTime
LocalTime lt1 = zdt1.toLocalTime();
LocalTime lt2 = zdt2.toLocalTime();
System.out.println(lt1);
System.out.println(lt2);
}
}
Output:
2020-10-22T08:00+01:00[Europe/London]
2020-10-26T08:00Z[Europe/London]
08:00
08:00

Related

How to convert a date with time zone offset to another format

I tried reading a lot about the date formatting with time zone, but it doesn't make sense to me.
My DB shows this datetime: 2022-12-01 04:00:00.000 +08:00
My UI shows it as: Thu 01/12/2022 12:00
I need to compare between them to verify they are the same. I tried to convert the DB time like this:
String dbDate = "2022-12-01 04:00:00.000 +08:00";
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS XXX");
Date date = sf.parse(dbDate)
sf = new SimpleDateFormat("EEE dd/MM/yyy HH:mm");
String uiDate = sf.format(date);
The results received is a completely different date: 'Wed 30/11/2022 22:02'.
I don't understand the logic here and would appreciate help in converting it correctly.
As already commented by Yonatan Karp-Rudin, you can not compare a date-time with time-zone offset with another without time-zone offset. A clear way to compare the two date-times is to bring them to a single time-zone e.g. you can apply the same time-zone offset to the UI date-time as of the DB date-time.
In March 2014, java.time API supplanted the error-prone legacy date-time API. Since then, it has been strongly recommended to use this modern date-time API.
Demo using java.time API:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String dt1 = "2022-12-01 04:00:00.000 +08:00";
String dt2 = "Thu 01/12/2022 12:00";
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS XXX", Locale.ENGLISH);
OffsetDateTime odt1 = OffsetDateTime.parse(dt1, dtf1);
System.out.println(odt1);
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("EEE dd/MM/uuuu HH:mm", Locale.ENGLISH)
.withZone(odt1.getOffset());
OffsetDateTime odt2 = OffsetDateTime.parse(dt2, dtf2);
System.out.println(odt2);
System.out.println(odt1.equals(odt2));
}
}
Output:
2022-12-01T04:00+08:00
2022-12-01T12:00+08:00
false
Assuming both the date-times belong to the same time-zone offset, another way to compare them would be compare them without time-zone i.e. comparing their date-time part only (LocalDateTime).
Demo:
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String dt1 = "2022-12-01 04:00:00.000 +08:00";
String dt2 = "Thu 01/12/2022 12:00";
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS XXX", Locale.ENGLISH);
LocalDateTime ldt1 = OffsetDateTime.parse(dt1, dtf1).toLocalDateTime();
System.out.println(ldt1);
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("EEE dd/MM/uuuu HH:mm", Locale.ENGLISH);
LocalDateTime ldt2 = LocalDateTime.parse(dt2, dtf2);
System.out.println(ldt2);
System.out.println(ldt1.equals(ldt2));
}
}
Output:
2022-12-01T04:00
2022-12-01T12:00
false
The modern date-time API (java.time API) provides you with tools to do the same thing in many ways e.g. in the 1st demo, we could obtain the OffsetDateTime for your UI date-time string by parsing it into a LocalDateTime as shown in the 2nd demo and then using one of the ways shown in this answer where ZoneOffset offset = odt1.getOffset().
By the way, here is an example of how you format a date-time with time-zone offset to another format:
public class Main {
public static void main(String[] args) {
String dtDb = "2022-12-01 04:00:00.000 +08:00";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS XXX", Locale.ENGLISH);
OffsetDateTime odtDb = OffsetDateTime.parse(dtDb, parser);
System.out.println(odtDb);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE dd/MM/uuuu HH:mm", Locale.ENGLISH);
String strDtUi = odtDb.format(formatter);
System.out.println(strDtUi);
}
}
Output:
2022-12-01T04:00+08:00
Thu 01/12/2022 04:00
Learn more about the modern Date-Time API from Trail: Date Time.

How to convert ZULU timestamp to Europe/Paris time zone?

I have a ZULU timestamp that I have to convert into Paris time zone.
ZULU 2022-11-04T06:10:08.606+00:00 --> Paris 2022-11-04T07:10:08.606+01:00
And have to take care of DST for example:
Summer time Hour +2 hour
Winter time Hour +1 hour
I have written the below code which is working as expected on the local but when deploy on the server (Paris) not working as expected.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Locale;
public class ParisTime {
public static void main(String[] args) throws ParseException {
// String date = "2022-05-31T23:30:12.209+00:00";
String date = "2022-11-04T06:10:08.606+00:00";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ENGLISH);
LocalDateTime dateTime = dateFormat.parse(date).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
ZonedDateTime of = ZonedDateTime.of(dateTime, ZoneId.of("Europe/Paris"));
String hourDiff = of.toString().substring(of.toString().indexOf('+') + 1, of.toString().indexOf('+') + 3);
String zonedDateTime = of.plusHours(Integer.valueOf(hourDiff)).toString();
String newDatetime = zonedDateTime.substring(0, of.toString().indexOf('['));
System.out.println(newDatetime);
System.out.println(dateFormat.parse(newDatetime));
}
}
Output
2022-11-04T07:10:08.606+01:00
Fri Nov 04 07:10:08 IST 2022
You can directly switch between zones and offsets using plain java.time, no legacy baggage necessary…
Here's how:
your input example is an ISO-formatted datetime with an offset from UTC (of 0 hours and 0 minutes, so it is Zulu time respectively in UTC), which means you can parse it in one go to a java.time.OffsetDateTime
an OffsetDateTime can be converted into a ZonedDateTime
a ZonedDateTime can handle daylight saving time (DST)
having a ZonedDateTime you can switch its ZoneId, which will respect DST, but keep the underlying instant
Please see the following example…
public static void main(String[] args) {
// input example
String date = "2022-11-04T06:10:08.606+00:00";
// directly parse it to a java.time.OffsetDateTime
OffsetDateTime odt = OffsetDateTime.parse(date);
// make the UTC/Zulu datetime zoned
ZonedDateTime zdt = odt.toZonedDateTime();
// print it
System.out.println(zdt);
// switch the zone to the desired one
ZonedDateTime zdtParis = zdt.withZoneSameInstant(ZoneId.of("Europe/Paris"));
// print that, too
System.out.println(zdtParis);
// or print a coversion to OffsetDateTime without explicitly mentioning the zone
System.out.println(zdtParis.toOffsetDateTime());
// the same can be achieved keeping the ZonedDateTime but formatting it as OffsetDateTime
System.out.println(zdtParis.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
}
The output of the above code is
2022-11-04T06:10:08.606Z
2022-11-04T07:10:08.606+01:00[Europe/Paris]
2022-11-04T07:10:08.606+01:00
2022-11-04T07:10:08.606+01:00
Try it with a datetime influenced by DST, you will see DST respected…
This is the output of the same code using the input value "2022-05-31T23:30:12.209+00:00":
2022-05-31T23:30:12.209Z
2022-06-01T01:30:12.209+02:00[Europe/Paris]
2022-06-01T01:30:12.209+02:00
2022-06-01T01:30:12.209+02:00
Your string is already in the format recognized by [static] method parse in class java.time.Instant. Then you can convert that instant to a ZonedDateTime in the Paris time zone. Two lines of code:
String date = "2022-11-04T06:10:08.606+00:00";
java.time.Instant inst = java.time.Instant.parse(date);
java.time.ZonedDateTime zdt = inst.atZone(java.time.ZoneId.of("Europe/Paris"));
It will also take into consideration changes for summer time and non-summer time.
ZULU : 2022-11-04T06:10:08.606Z
Paris: 2022-11-04T07:10:08.606+01:00[Europe/Paris]

Java date parsing has stranger behavior where parsing different date in different timezone

Here I am trying to parse two dates in java. Date 1 is "2021-01-01" and date 2 is "2021-04-01". But after parsing Java generating Date object with a different timezone. Really confused by this behavior. I am looking at the same timezone and that is EDT.
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class DateCalculation {
private static final DateFormat formater = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
public static void main(String args[]) throws ParseException {
Date date1 = getDateFromString("2021-01-01");
System.out.println("Date 1: " + date1);
Date date2 = getDateFromString("2021-04-01");
System.out.println("Date 2: " + date2);
}
public static Date getDateFromString(String dateString) throws ParseException {
if(dateString == null || dateString.trim().length() == 0)
return null;
dateString = dateString.replace("\"", ""); // Remove quotes
return formater.parse(dateString);
}
}
Output:
Date 1: Fri Jan 01 00:00:00 EST 2021
Date 2: Thu Apr 01 00:00:00 EDT 2021
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310.
LocalDate
For a date-only value without time-of-day and without time zone, use LocalDate class.
LocalDate.parse( "2021-04-01" )
ZonedDateTime
If you want to represent the first moment of the day for that date in a particular time zone, apply ZoneId to get a ZonedDateTime.
Do not assume the day starts at 00:00:00 🕛. Some dates in some zones start at another time such as 01:00:00 🕐. So let java.time determine the first moment.
EDT is not a real time zone. Perhaps you meant America/Montreal, America/New_York, America/Indiana/Marengo, or some such.
LocalDate ld = LocalDate.parse( "2022-01-23" ) ;
ZoneId z = ZoneId.of( "America/Indiana/Marengo" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;

Why GregorianCalendar randomly add "Z" at the end of date and sometimes don't

I had to get the current date, add 20 years, and transferred it in an XML object.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "XMLCommande", propOrder = {
...
"dateLivSouhaitee",
...
})
public class XMLCommande {
...
#XmlElement(name = "date_liv_souhaitee", required = true)
#XmlSchemaType(name = "date")
protected XMLGregorianCalendar dateLivSouhaitee;
...
}
No date format is specified, it's all by default :
XMLCommande xmlMessage = new XMLCommande();
GregorianCalendar gregorianCalendar = new GregorianCalendar();
gregorianCalendar.add(Calendar.YEAR, 20);
ligne.setDateLivSouhaitee(DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar2));
The problem, is, for some unknown reason, that's sometimes I have a "Z" at the end of the date, but sometimes don't :
<date_liv_souhaitee>2041-05-26Z</date_liv_souhaitee>
<date_liv_souhaitee>2041-05-26+02:00</date_liv_souhaitee>
It's the same server, why sometimes I have the Z with "+02:00" and sometimes don't ?
How can I force the format to be always :
<date_liv_souhaitee>2041-05-26+02:00</date_liv_souhaitee>
The Z in the date-time string 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).
In the other case, you have +02:00 timezone offset added in the date-time string i.e. the corresponding date-time in UTC will be the given date-time minus 2 hours. You can convert the UTC date-time into date-time with +02:00 timezone offset e.g.
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class Main {
public static void main(String[] args) throws DatatypeConfigurationException {
ZonedDateTime zdtUtc = LocalDate.of(2041, 5, 26).atStartOfDay(ZoneOffset.UTC);
System.out.println(zdtUtc);
ZonedDateTime zdtOffsetTwoHrs = zdtUtc.withZoneSameInstant(ZoneOffset.of("+02:00"));
System.out.println(zdtOffsetTwoHrs);
GregorianCalendar gregorianCalendar = GregorianCalendar.from(zdtOffsetTwoHrs);
XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gregorianCalendar);
System.out.println(xmlGregorianCalendar);
}
}
Output:
2041-05-26T00:00Z
2041-05-26T02:00+02:00
2041-05-26T02:00:00.000+02:00
Why do I sometimes get the Z and sometimes +02:00?
If both come from creating a GregorianCalendar using the no-arg constructor and converting it to XMLGregorianCalendar, then the best explanation is that someone is modifying the default time zone of your JVM. A part of your own program may do that or some other program running in the same JVM. To demonstrate:
TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Europe/Paris")));
GregorianCalendar gc = new GregorianCalendar();
System.out.println(DatatypeFactory.newInstance().newXMLGregorianCalendar(gc));
TimeZone.setDefault(TimeZone.getTimeZone(ZoneOffset.UTC));
gc = new GregorianCalendar();
System.out.println(DatatypeFactory.newInstance().newXMLGregorianCalendar(gc));
Output from these code lines was:
2021-05-26T19:41:29.744+02:00
2021-05-26T17:41:29.776Z
new GregorianCalendar() creates a GregorianCalendar that has the default time zone of the JVM at the time of creation. As Arvind Kumar Avinash already explained, offset 0 from UTC is rendered as Z in accordance with the ISO 8601 standard.
How can I force +02:00 always?
I recommend that you use java.time, the modern Java date and time API, for your date work. The OffsetDateTime class represents a date and time with a UTC offset, so just set the offset to +2.
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.ofHours(2));
OffsetDateTime in20Years = now.plusYears(20);
String dateStringWithOffset0200 = in20Years.format(DateTimeFormatter.ISO_OFFSET_DATE);
System.out.println(dateStringWithOffset0200);
2041-05-26+02:00
If you do need an XMLGregorianCalendar, build one from the string we just got:
XMLGregorianCalendar xmlgc = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(dateStringWithOffset0200);
System.out.println(xmlgc);
2041-05-26+02:00
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601

Convert integer date time into real date time problem? JAVA [duplicate]

This question already has answers here:
Convert Json date to java date
(3 answers)
How can I convert Json Date to Java Date
(6 answers)
Closed 2 years ago.
so I have this problem converting Integer DateTime format to normal DateTime format in Java.
I have this this variable int DateTime, for example it is : "/Date(1484956800000)/" . And i am trying to convert it to normal date time and show it to the screen ...
I tried like this..
String dateAsText = new SimpleDateFormat("MM-dd HH:mm")
.format(new Date(Integer.parseInt(deals.getDate_time()) * 1000L));
// setting my textView with the string dateAsText
holder.Time.setText(dateAsText);
I suggest you stop using the outdated and error-prone java.util date-time API and SimpleDateFormat. Switch to the modern java.time date-time API and the corresponding formatting API (java.time.format). Learn more about the modern date-time API from Trail: Date Time.
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// Obtain an instance of Instant using milliseconds from the epoch of
// 1970-01-01T00:00:00Z
Instant instant = Instant.ofEpochMilli(1484956800000L);
System.out.println(instant);
// Specify the time-zone
ZoneId myTimeZone = ZoneId.of("Europe/London");
// Obtain ZonedDateTime out of Instant
ZonedDateTime zdt = instant.atZone(myTimeZone);
// Obtain LocalDateTime out of ZonedDateTime
// Note that LocalDateTime throws away the important information of time-zone
LocalDateTime ldt = zdt.toLocalDateTime();
System.out.println(ldt);
// Custom format
String dateAsText = ldt.format(DateTimeFormatter.ofPattern("MM-dd HH:mm"));
System.out.println(dateAsText);
}
}
Output:
2017-01-21T00:00:00Z
2017-01-21T00:00
01-21 00:00
If you still want to use the poorly designed legacy java.util.Date, you can do it as follows:
import java.text.SimpleDateFormat;
import java.util.Date;
public class Main {
public static void main(String[] args) {
Date date = new Date(1484956800000L);
System.out.println(date);
// Custom format
String dateAsText = new SimpleDateFormat("MM-dd HH:mm").format(date);
System.out.println(dateAsText);
}
}
Output:
Sat Jan 21 00:00:00 GMT 2017
01-21 00:00

Categories