How Can I Get the Current Date and Time in UTC or GMT in Java?

Let's get some things straight around time and time zones in Java!

One of the key questions developers have in every programming language is the one related to time and time zones. Before we see how to get the current date and time in UTC or GMT in Java, there are a few concepts we need to make ourselves familiar with.

First things first, GMT (Greenwich Mean Time) is not the same as UTC (Coordinated Universal Time):

  • GMT is a time zone used in some but not all parts of the world (mainly Europe and Africa). It uses either a 24-hour format or a 12-hour format for display, and it’s based on astronomical observations.
  • UTC is not a time zone. It is a standard that we can use to display time zones. It is more stable as it takes time from an atomic clock.

If you are using the java.util.date package to get the current date and time in Java (as it looks more intuitive), you’ll soon find out it’s very limited. There are several reasons for that:

  • It doesn’t have a time zone.
  • It doesn’t represent a date but an instance in time in milliseconds since the Unix epoch (1970).

Therefore, if you want to get swiftly the current time in milliseconds only, you can use the following code:

package com.thdespou;

import java.util.Date;

public class Main {

    public static void main(String[] args) {
        // Date
        Date now = new Date();
        System.out.println("Current Date in milliseconds is :" + now.getTime());
    }
}

Other than that, you can also change the current system, TimeZone, and if you wanted to use a different time zone, you could do it as follows:

package com.thdespou;

import java.util.Date;
import java.util.TimeZone;

public class Main {

    public static void main(String[] args) {
        // Date
        Date now = new Date();
        System.out.println("Current Date in milliseconds is :" + now.getTime());

        // Display the instant in three different time zones
        TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
        System.out.println(now);

        TimeZone.setDefault( TimeZone.getTimeZone("GMT"));
        System.out.println(now);

        TimeZone.setDefault( TimeZone.getTimeZone("UTC"));
        System.out.println(now);
    }
}

However, if you run this code, you’ll see the following output:

Current Date in milliseconds is :1583954404789
Wed Mar 11 19:20:04 GMT 2020
Wed Mar 11 19:20:04 GMT 2020
Wed Mar 11 19:20:04 UTC 2020

In general, this is not ideal, as it displays the current time based on the time zone of the specified region, which may be different than GMT; therefore, it should be avoided.

A better and more modern option bundled within the Java Core library (and not using any third-party offerings) is to use the java.time package.

If you look at the documentation page, the package is based on the ISO calendar system and offers a simplified API for displaying and handling date and time instances. Bellow is the depicted table of the capabilities exposed in this package:

Time Table Java

Based on this, we can infer that this package represents the time (with the location unspecified), as UTC, or as an offset from UTC.

Indeed, if we check the Instant class to get the current time, we can see the date time printed as UTC:

package com.thdespou;

import java.time.Instant;

public class Main {

    public static void main(String[] args) {
        Instant now = Instant.now();
        System.out.println("Date is " + now);
    }
}

This will display:

Date is 2020-03-11T20:39:20.480918Z

Which is the current date-time in UTC. The ending Z character denotes the Zone Offset which is Zero.

A more robust option is to convert this Instance to a ZonedDateTime as you’d like to configure the current TimeZone. You can do that by using the ofInstant static factory method passing a ZoneId:

package com.thdespou;

import java.time.*;

public class Main {

    public static void main(String[] args) {
        Instant now = Instant.now();
        ZonedDateTime zdt = ZonedDateTime.ofInstant(now,
                ZoneId.systemDefault());

        System.out.println( "Date is: " + zdt );
    }
}

In most cases, you should be using the UTC format as it’s best supported in Java.

How do I set the default locale for my JVM?

Locales identify a specific language and geographic region; they’re represented as strings in the following format:

[language[_territory][.codeset][@modifier]]

Here’s an example of some locale strings:

eo_KE
no_NO
ca_AD
zh_MO_#Hant
en_SH

If you run a UNIX platform (Mac, Linux), there’s a convention to set some environmental variables using the LC_* prefix. For example, by running this command in the console, we can see en_IE as the default system locale:

➜ locale
LANG="en_IE.UTF-8"
LC_COLLATE="en_IE.UTF-8"
LC_CTYPE="en_IE.UTF-8"
LC_MESSAGES="en_IE.UTF-8"
LC_MONETARY="en_IE.UTF-8"
LC_NUMERIC="en_IE.UTF-8"
LC_TIME="en_IE.UTF-8"
LC_ALL=

In Java, if we call the Locale.getDefault() in a method and run the java command without any flags, it won’t pick up the system locale as specified in the LC_* variables. For example, given the following main class, located in com/thdespou/Main.java:

package com.thdespou;

import java.util.Locale;

public class Main {

    public static void main(String[] args) {
        System.out.println(Locale.getDefault());
    }
}
$ javac com/thdespou/Main.java

$ java -classpath $(pwd) com/thdespou/Main 
en_IE

Now, if we change the LC_* variables to en_UK, it will still print en_IE.

In fact, looking at the Locale documentation page, there is no information on how to change that. However, by inspecting the source code of the Locale.class and particularly the static initializer block …

static {
...
defaultLocale = initDefault();
}

… and looking at the initDefault() method, we get a hint of what we exactly need to do in order to set the default locale in the JVM:

private static Locale initDefault() {
    Properties props = GetPropertyAction.privilegedGetProperties();
    String language = props.getProperty("user.language", "en");
    String region = props.getProperty("user.region");
    String script;
    String country;
    String variant;
    if (region != null) {
        int i = region.indexOf(95);
        if (i >= 0) {
            country = region.substring(0, i);
            variant = region.substring(i + 1);
        } else {
            country = region;
            variant = "";
        }

        script = "";
    } else {
        script = props.getProperty("user.script", "");
        country = props.getProperty("user.country", "");
        variant = props.getProperty("user.variant", "");
    }

So using the following system properties:

user.language: For setting the current language

user.region: For setting the language region

Given that information, we can check in the command line for setting the default locale and using this guide. For example:

$ java -Duser.language=el -Duser.region=CY com.thdespou.Main
el_CY
$ java -Duser.language=zh -Duser.region=hans_chinese com.thdespou.Main
zh_HANS_chinese

Note that this is based on this implementation of the JVM, and we should not be if this would change in the future, as it is not clearly documented in the JavaDocs.

5 (100.17%) 116 votes
Comments
close

Best Practices for Successful Localization

Download your FREE EBOOK copy to get:

  • Insider insights from product managers
  • Tips and tricks from localization specialists
  • Concise chapter summaries for easy review
  • Our ultimate checklist to track your progress