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

Date and time in Java

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

One of the key questions developers have in every programming language is the one related to time and timezones. Before we try to answer how you can get the current date and time in UTC or GMT in Java, there are a few concepts you need to understand.

To begin with, GMT (which stands for Greenwich Mean Time) is not the same as UTC (which stands for 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 its based on astronomical observations.
  • UTC is not a time zone. It is a standard which 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 will find out soon it’s very limited. There are several reasons for that:

  • It doesn’t have a time zone.
  • It doesn’t represent a date. It represents 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 timezone, you could do it like this:

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 will 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 prints the current time based on the timezone 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 would 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 UTC format as they are mostly supported in Java.

How do I set the default locale for my JVM?

First of all, to understand how to set the default locale, you need to know what locale is. Locales identify a specific language and geographic region. They are represented as strings using the following format:

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

For example, here are some Locale strings:

eo_KE
no_NO
ca_AD
zh_MO_#Hant
en_SH

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

➜ 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 will not 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.

Ready for More?

We have more popular questions with detailed answers around localization coming soon. I hope I could help you learn some useful things along the way. Stay put for the next part promptly.

5 (100%) 10 votes
Comments
close

Automate Your Localization Workflow for Continuous Deployment

Automate Localization for Continuous Deployment

  • Integrate Phrase into your agile environment easily
  • Import and export your localization files in any format
  • Automate your localization workflow to speed up every release