skip to Main Content

Recently I created a VM on Google Cloud Platform to run my .jar 24/7, and a part of my code is like:

if (LocalTime.now().getHour() == 0)
    whenDateChanged();

I noticed that it runs at 12 am UTC+0, but I want it to run at 12 am UTC+8, so I use this command in terminal to change the time zone of my server:

sudo timedatectl set-timezone "Asia/Taipei"

After I reboot my server, the whenDateChanged() stills runs at 8 am UTC+8, why did this happened?

Java version: 21.0.3
OS: Debian GNU/Linux, 12 (bookworm)

2

Answers


  1. Certainly! Here’s a revised explanation in a more conversational tone:


    The reason LocalTime.now() still returns the same value even after changing the server’s time zone is because LocalTime doesn’t actually consider time zones. It simply reflects the current time according to the system clock, regardless of the time zone setting on your server.

    To ensure your code respects the new time zone (Asia/Taipei), you need to use ZonedDateTime instead of LocalTime. Here’s how you can adjust your code:

    import java.time.*;
    
    // Use ZonedDateTime to get the current time in a specific time zone
    if (ZonedDateTime.now(ZoneId.of("Asia/Taipei")).getHour() == 0) {
        whenDateChanged();
    }
    

    In this updated code:

    • ZonedDateTime.now(ZoneId.of("Asia/Taipei")) gives you the current date and time in the Asia/Taipei time zone.
    • .getHour() retrieves the hour part of the current time in Taipei time.
    • This ensures that your whenDateChanged() method is triggered correctly at midnight (00:00) in Taipei time (UTC+8).

    By using ZonedDateTime, you’re explicitly telling Java to consider the specified time zone (Asia/Taipei), which will reflect the change you made using timedatectl on your server.

    This approach should resolve the issue and align with your requirement to run whenDateChanged() at midnight in UTC+8 (Taipei time) after changing the server’s time zone setting.

    Hope this helps clarify things for you!

    Login or Signup to reply.
  2. tl;dr

    if ( LocalTime.now( ZoneId.of( "Asia/Singapore" ) ).getHour() == 0 ) { … }
    

    Specify time zone in Java

    LocalTime.now()

    You omitted the time zone argument to that method call. So Java implicitly applied the JVM’s current default time zone.

    Depending on such a default pits the success of your app against the whims of a system administrator who mach change that default.

    I suggest you instead specify explicitly your desired/expected time zone.

    First, get the name of your desired time zone. Real time zones have a name in the format of Continent/Region.

    Since you mentioned an interest in an offset of eight hours ahead of UTC, I arbitrarily chose Asia/Singapore. That zone is currently using an offset of +08:00.

    ZoneId zoneId = ZoneId.of( "Asia/Singapore" ) ;
    LocalTime timeNow = LocalTime.now( zoneId ) ;
    

    so I use this command in terminal to change the time zone of my server:

    No, no, no.

    Just ignore the time zone of your server. Write your Java code to always specify your desired/expected time zone, as shown above.

    And, by the way, servers should generally be set to UTC (an offset of zero hours-minutes-seconds). Programmers and sysadmins should both learn to think of UTC (an offset of zero) to be the One True Time. All time zones are but a variation.

    Generally, all your logging, data exchange, data storage, and business logic should be in UTC unless there is a clear and present reason otherwise. I suggest programmers & sysadmins keep a clock on their desk set to UTC. Trying to work, and convert to/from, your parochial time zone is confusing, error-prone, and distracting. While on the job, think in UTC.

    After I reboot my server, the whenDateChanged() stills runs at 8 am UTC+8, why did this happened?

    Since your current code implicitly relies upon the JVM’s current default time zone, your need to examine the JVM’s current default time zone, not the host operating system’s current default time zone.

    System.out.println( ZoneId.systemDefault() );
    

    Some JVM implementations may set their current default time zone to be that of the host OS, as detected at launch. But this is not necessarily the case. For example, the admin launching the JVM at deployment may be specifying a time zone for the JVM to use as its default. I have no idea what Google Cloud Platform may be doing.

    👉🏽 The real solution is to not depend on the host OS’s current default time zone, nor the JVM’s current default time zone. Instead, specify a time zone.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search