0

I'm converting a long number from server to local Datetime. The server time zone is GMT and we are converting to local Date time.

My question is there any simple method to do this as I'm pretty sure the below code is somewhat CPU expensive. Any simple method with fewer code like adding or subtracting numbers would be great.

My code - Java Code convert TimeZone

    Long update_time = System.currentTimeMillis();
    Date date = new Date(update_time);
    Format format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
    ZonedDateTime dateTime = ZonedDateTime.parse( format.format(date) + " GMT", formatter);
    ZoneId zone = ZoneId.of("Asia/Kolkata");
    ZoneId zone1 = ZoneId.systemDefault();
    ZonedDateTime dt1 = dateTime.withZoneSameInstant(zone);
    
    //ZonedDateTime utc = ZonedDateTime.parse( format.format(date)  );
    System.out.println("Original time: " + format.format(date));
    System.out.println("Parsed time: " + dateTime.format(formatter) );
    System.out.println("Local time: " + dt1.format(formatter) );
Pradyut Bhattacharya
  • 5,440
  • 13
  • 53
  • 83
  • 1
    Do not mix the use of legacy and modern date-time classes. Always use *java.time* classes. Never use the terrible classes `Date`, `Calendar`, `SimpleDateFormat`, etc. – Basil Bourque Jun 07 '21 at 16:21
  • Time zones are complicated, so the conversion will never be without a cost in CPU cycles. I believe you can gain some by simplifying your code, though. – Ole V.V. Jun 07 '21 at 17:36
  • What makes you think that your code is prohibitively expensive in CPU time? How many million times are you performing this conversion since the time it takes may matter? – Ole V.V. Jun 08 '21 at 03:35
  • 1
    I'm updating a list of many users who are online or recently seen every 5 seconds – Pradyut Bhattacharya Jun 08 '21 at 11:50

2 Answers2

4

I do not know why you are mixing the legacy API and the modern API.

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Demo using java.time, the modern Date-Time API:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        Instant now = Instant.now();
        ZonedDateTime zdt = now.atZone(ZoneId.of("Asia/Kolkata"));
        System.out.println(zdt);
    }
}

Output:

2021-06-07T21:47:30.271351+05:30[Asia/Kolkata]

ONLINE DEMO


* 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.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
-1

Well I could get the time difference in the below code

I will simply calculate the local time by adding or subtracting from the original long number I get from the server unless the user changes the system timezone which they seldom do. I can check that once in a while.

This simple addition/subtraction saves a lot a CPU time.

Well I wish I could convert the code easily to java.time.* but will try later

Code Link

    Long update_time = System.currentTimeMillis();
    Date date = new Date(update_time);
    Format format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS z");
    DateTimeFormatter f1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
    ZonedDateTime dateTime = ZonedDateTime.parse( format.format(date) + " GMT", formatter);
    ZoneId zone = ZoneId.of("Asia/Kolkata");
    ZoneId zone1 = ZoneId.systemDefault();
    ZonedDateTime dt1 = dateTime.withZoneSameInstant(zone);
    
    //ZonedDateTime utc = ZonedDateTime.parse( format.format(date)  );
    System.out.println("Original time: " + format.format(date));
    System.out.println("Parsed time: " + dateTime.format(formatter) );
    System.out.println("Local time: " + dt1.format(formatter) );
    
    SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    try {
    Date d = (Date)f.parse(dt1.format(f1));
    
    System.out.println("Long time: " + d.getTime() );
    System.out.println("System time: " + update_time );
    System.out.println("Time Difference: " + (d.getTime() - update_time) ); // this remains the same if local timezone is not changed
    } catch(Exception e) { System.out.println("Exception: " + e.toString() ); }
Pradyut Bhattacharya
  • 5,440
  • 13
  • 53
  • 83
  • Your assumption is wrong. So is your approach. By adding or subtracting a difference you are not converting to a the same time in a different time zone, you are converting to a different time. You might expect that to be an ugly hack working for a time zone that has a constant offset from UTC. Such a time zone hardly exists, and Asia/Kolkata certainly isn’t one. – Ole V.V. Jun 08 '21 at 03:20
  • I didn’t do any [benchmark](https://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java) to see if you code saves time, or how much. Did you? If so, how much does it save? – Ole V.V. Jun 08 '21 at 03:22
  • If performance really matters (I am not yet convinced), you may also want to measure how much time the much simpler code in the answer by Arvind Kumar Avinash saves compared to yours. – Ole V.V. Jun 08 '21 at 03:34
  • @OleV.V. you missed the line ZoneId zone1 = ZoneId.systemDefault(); which will give the offset for the local machine. – Pradyut Bhattacharya Jun 08 '21 at 11:42