Home > Blockchain >  Date conversion: add UTCOffset to existing timezone
Date conversion: add UTCOffset to existing timezone

Time:01-30

I have date which is in the format of(example) Date = 2023-01-09T23:51:44.595Z and I have utcOffset String utcOffset = "UTC 6"

I want output as 2023-01-10T05:51:44.595Z in Date format.

How to achieve this??

I should add UTC offset to existing date.

Tried this:

public static void main(String[] args) throws ParseException {
        String rawDate = "2023-01-09T23:51:44.595Z";
        String utcOffset = "UTC  6";

        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT);
        Date date = (Date) formatter.parse(rawDate);
        SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT);
        String v = formatter1.format(date);
        System.out.println("Original raw date::::::::::" v);
        
        System.out.println("utcOffset::::::::::" utcOffset);

        Date triggerTime = date;
        String onlyHoursAndMin = StringUtils.strip(utcOffset, "UTC ");

        String[] split = onlyHoursAndMin.split(":");
        int hours = Integer.parseInt("0");
        int minutes = Integer.parseInt("0");
        if (split.length == 2) {
            hours = Integer.parseInt(split[0]);
            minutes = Integer.parseInt(split[1]);
        } else if (split.length == 1) {
            hours = Integer.parseInt(split[0]);
            minutes = Integer.parseInt("0");
        }

        TimeZone timeZone = TimeZone.getTimeZone("UTC");
        Calendar calendar = Calendar.getInstance(timeZone);
        calendar.setTime(triggerTime);
        calendar.add(Calendar.HOUR_OF_DAY, hours);
        calendar.add(Calendar.MINUTE, minutes);
        Date s = calendar.getTime();
        
        SimpleDateFormat utcFormatter1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT);
        String newDate = utcFormatter1.format(s);
        System.out.println("Date in string format::::::::::::::" newDate);
        
        SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT);
        SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT);
        Date aaa = format1.parse(newDate);
        String bbb = format2.format(aaa);
        System.out.println(":::::::::::::" aaa);
        System.out.println("Date in correct format::::::::::::::" format2.format(aaa));
        
    }

but finale Date format is Tue Jan 10 05:51:44 IST 2023 which is not expected.

and when build I am getting below error as well: Forbidden method invocation: java.util.Calendar#getInstance(java.util.TimeZone) [Uses default locale or time zone]

CodePudding user response:

I would suggest to move away from the legacy API (java.util.Date, java.util.Calendar, etc.), it is cumbersome and error prone. Since java 8 the modern date-time API, java.time, is available. With it the task would be quite trivial.

String date = "2023-01-09T23:51:44.595Z";
OffsetDateTime oldDateTime = OffsetDateTime.parse(date);
System.out.println("old - "   oldDateTime);
ZoneOffset offset = ZoneOffset.ofHours(6);
OffsetDateTime newDateTime = oldDateTime.withOffsetSameInstant(offset);
System.out.println("new - "   newDateTime);

Prints time - 2023-01-10T05:51:44.595 06:00.

Note that it ends with 06:00, not Z. Z at the end of a date-time string means Zulu, which indicates that the time is in UTC - What is the Z ending on date strings like 2014-01-01T00:00:00.588Z. Since resulting time is UTC 6 hours, a date sting 2023-01-10T05:51:44.595Z would be incorrect.

CodePudding user response:

java.time

The java.util date-time API and their corresponding parsing/formatting type, SimpleDateFormat are outdated and error-prone. In March 2014, the modern Date-Time API was released as part of the Java 8 standard library which supplanted the legacy date-time API and since then it is strongly recommended to switch to java.time, the modern date-time API.

Solution using java.time

  1. java.time API is based on ISO 8601 and therefore you do not need a DateTimeFormatter to parse a date-time string which is already in ISO 8601 format e.g. your date-time string, 2023-01-09T23:51:44.595Z which can be directly parsed into an OffsetDateTime.
  2. Your offset string is not in the ISO 8601 standard format. The standard format is /-HH:mm:ss or Z which refers to 00:00 offset. In most cases, you will see /-HH:mm e.g. 06:00. You can choose any basic string manipulation technique to get the hours and minutes from your string and create a ZoneOffset instance using them. I have used one which I have found easy to do.

The rest of the code is straightforward.

Demo:

import java.time.OffsetDateTime;
import java.time.ZoneOffset;

class Main {
    public static void main(String[] args) {
        String strDateTime = "2023-01-09T23:51:44.595Z";
        String utcOffset = "UTC  6";
        int offsetHour = Integer.parseInt(utcOffset.replaceAll("[^0-9 -]", ""));
        ZoneOffset zoneOffset = ZoneOffset.ofHours(offsetHour);
        OffsetDateTime odtGiven = OffsetDateTime.parse(strDateTime);
        OffsetDateTime odtDesired = odtGiven.withOffsetSameLocal(zoneOffset)
                                        .withOffsetSameInstant(zoneOffset.UTC);
        System.out.println(odtDesired);
    }
}

Output:

2023-01-09T17:51:44.595Z

Note that 2023-01-10T05:51:44.595Z does not make sense without am/pm marker as you mean 05:51:44.595 pm. You can use a DateTimeFormatter to format it in your desired way.

ONLINE DEMO

Learn more about the modern Date-Time API from Trail: Date Time.

  • Related