GMT+02:00 is a custom ID, it won't appear in the output of TimeZone.getAvailableIDs() (which is huge). What you could do is to ask the user to specify his offset first and then get the available IDs for the given offset. For example, for GMT+02:00, the following piece of code:

for (String string : TimeZone.getAvailableIDs(TimeZone.getTimeZone(
        "GMT+02:00").getRawOffset())) {
    System.out.println(string);
}

gives the following output:

ART
Africa/Blantyre
Africa/Bujumbura
Africa/Cairo
Africa/Gaborone
Africa/Harare
Africa/Johannesburg
Africa/Kigali
Africa/Lubumbashi
Africa/Lusaka
Africa/Maputo
Africa/Maseru
Africa/Mbabane
Africa/Tripoli
Asia/Amman
Asia/Beirut
Asia/Damascus
Asia/Gaza
Asia/Istanbul
Asia/Jerusalem
Asia/Nicosia
Asia/Tel_Aviv
CAT
EET
Egypt
Etc/GMT-2
Europe/Athens
Europe/Bucharest
Europe/Chisinau
Europe/Helsinki
Europe/Istanbul
Europe/Kaliningrad
Europe/Kiev
Europe/Mariehamn
Europe/Minsk
Europe/Nicosia
Europe/Riga
Europe/Simferopol
Europe/Sofia
Europe/Tallinn
Europe/Tiraspol
Europe/Uzhgorod
Europe/Vilnius
Europe/Zaporozhye
Israel
Libya
Turkey

It's still big but human browsable this time.

Answer from Pascal Thivent on Stack Overflow
🌐
Oracle
docs.oracle.com › cd › E72987_01 › wcs › tag-ref › MISC › TimeZones.html
TimeZoneID
The following table lists the TimeZoneID that you can use with the Date Format Tags. Time Zone ID Description MIT West Samoa Time Pacific/Apia West Samoa Time Pacific/Niue Niue Time Pacific/Pago_Pago Samoa Standard Time America/Adak Hawaii-Aleutian Standard Time HST Hawaii Standard Time ...
🌐
Gary Gregory
garygregory.wordpress.com › 2013 › 06 › 18 › what-are-the-java-timezone-ids
What are the Java TimeZone IDs? | Gary Gregory
September 9, 2015 - Here is an example of the available IDs returned by java.util.TimeZone#getAvailableIDs(). Oracle Corporation's version 1.7.0_79 has 623 time zone IDs: ACT AET AGT ART AST Africa/Abidjan Africa/Accra Africa/Addis_Ababa Africa/Algiers Africa/Asmara Africa/Asmera Africa/Bamako Africa/Bangui Africa/Banjul Africa/Bissau Africa/Blantyre Africa/Brazzaville Africa/Bujumbura Africa/Cairo Africa/Casablanca Africa/Ceuta Africa/Conakry Africa/Dakar Africa/Dar_es_Salaam Africa/Djibouti Africa/Douala Africa/El_Aaiun Africa/Freetown Africa/Gaborone Africa/Harare Africa/Johannesburg Africa/Juba Africa/Kampala Africa/Khartoum Africa/Kigali…
Discussions

How can I get the current date and time in UTC or GMT in Java? - Stack Overflow
Then we convert to having only ... time zone (a history of past, present, and future changes in the offset used by the people of a particular region). Lastly, we generate text representing the value in that OffsetDateTime per the standard ISO 8601 format used by default in its toString method. 2019-04-26T04:15:16.967Z+00:00 ... @RudraTiwari java.time uses ... More on stackoverflow.com
🌐 stackoverflow.com
date - Java 8 - tz database time zones - Stack Overflow
The best practice is to do most everything in UTC: your logging, your business logic, your data storage, and your data exchange/serialization. Use a time zone only where required by the business problem or for presentation to a user. The basic java.time class for a UTC value is Instant as in ... More on stackoverflow.com
🌐 stackoverflow.com
datetime - Java 8 timezone conversion - Stack Overflow
I know there are similar questions like this, but I wasn't quite able to find the example similar to mine. I learned about LocalDateTime and ZonedDateTime but I don't know how to tell my ZonedDateTime what's assumed timezone of parsed date. I'm migrating from Java 7 to Java 8. More on stackoverflow.com
🌐 stackoverflow.com
How to list Java TimeZones relevant to end-user? - Stack Overflow
I am allowing users on my web app to schedule events based on time zones of their choice. I want to present a good list of time zones to the end user and then convert it easily to java.util.TimeZone More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 7
35

GMT+02:00 is a custom ID, it won't appear in the output of TimeZone.getAvailableIDs() (which is huge). What you could do is to ask the user to specify his offset first and then get the available IDs for the given offset. For example, for GMT+02:00, the following piece of code:

for (String string : TimeZone.getAvailableIDs(TimeZone.getTimeZone(
        "GMT+02:00").getRawOffset())) {
    System.out.println(string);
}

gives the following output:

ART
Africa/Blantyre
Africa/Bujumbura
Africa/Cairo
Africa/Gaborone
Africa/Harare
Africa/Johannesburg
Africa/Kigali
Africa/Lubumbashi
Africa/Lusaka
Africa/Maputo
Africa/Maseru
Africa/Mbabane
Africa/Tripoli
Asia/Amman
Asia/Beirut
Asia/Damascus
Asia/Gaza
Asia/Istanbul
Asia/Jerusalem
Asia/Nicosia
Asia/Tel_Aviv
CAT
EET
Egypt
Etc/GMT-2
Europe/Athens
Europe/Bucharest
Europe/Chisinau
Europe/Helsinki
Europe/Istanbul
Europe/Kaliningrad
Europe/Kiev
Europe/Mariehamn
Europe/Minsk
Europe/Nicosia
Europe/Riga
Europe/Simferopol
Europe/Sofia
Europe/Tallinn
Europe/Tiraspol
Europe/Uzhgorod
Europe/Vilnius
Europe/Zaporozhye
Israel
Libya
Turkey

It's still big but human browsable this time.

2 of 7
9

java.time.ZoneId

TimeZone is part of the troublesome old date-time classes that are now legacy, supplanted by the java.time classes.

In your case, look at ZoneId and ZoneOffset. An offset-from-UTC is a number of hours and minutes. A time zone is a history of past, present, and future offsets in use by a region over various periods of time.

Get a collection of all known zones via ZoneId.getAvailableZoneIds. Be sure your JVM has been updated recently enough with info about all time zones in which you have an interest. Politicians have a surprising propensity for frequently changing zone definitions, often with little forewarning.

Set < String > ids = ZoneId.getAvailableZoneIds() ;

As of Java 8 Update 144.

[Asia/Aden, America/Cuiaba, Etc/GMT+9, Etc/GMT+8, Africa/Nairobi, America/Marigot, Asia/Aqtau, Pacific/Kwajalein, America/El_Salvador, Asia/Pontianak, Africa/Cairo, Pacific/Pago_Pago, Africa/Mbabane, Asia/Kuching, Pacific/Honolulu, Pacific/Rarotonga, America/Guatemala, Australia/Hobart, Europe/London, America/Belize, America/Panama, Asia/Chungking, America/Managua, America/Indiana/Petersburg, Asia/Yerevan, Europe/Brussels, GMT, Europe/Warsaw, America/Chicago, Asia/Kashgar, Chile/Continental, Pacific/Yap, CET, Etc/GMT-1, Etc/GMT-0, Europe/Jersey, America/Tegucigalpa, Etc/GMT-5, Europe/Istanbul, America/Eirunepe, Etc/GMT-4, America/Miquelon, Etc/GMT-3, Europe/Luxembourg, Etc/GMT-2, Etc/GMT-9, America/Argentina/Catamarca, Etc/GMT-8, Etc/GMT-7, Etc/GMT-6, Europe/Zaporozhye, Canada/Yukon, Canada/Atlantic, Atlantic/St_Helena, Australia/Tasmania, Libya, Europe/Guernsey, America/Grand_Turk, US/Pacific-New, Asia/Samarkand, America/Argentina/Cordoba, Asia/Phnom_Penh, Africa/Kigali, Asia/Almaty, US/Alaska, Asia/Dubai, Europe/Isle_of_Man, America/Araguaina, Cuba, Asia/Novosibirsk, America/Argentina/Salta, Etc/GMT+3, Africa/Tunis, Etc/GMT+2, Etc/GMT+1, Pacific/Fakaofo, Africa/Tripoli, Etc/GMT+0, Israel, Africa/Banjul, Etc/GMT+7, Indian/Comoro, Etc/GMT+6, Etc/GMT+5, Etc/GMT+4, Pacific/Port_Moresby, US/Arizona, Antarctica/Syowa, Indian/Reunion, Pacific/Palau, Europe/Kaliningrad, America/Montevideo, Africa/Windhoek, Asia/Karachi, Africa/Mogadishu, Australia/Perth, Brazil/East, Etc/GMT, Asia/Chita, Pacific/Easter, Antarctica/Davis, Antarctica/McMurdo, Asia/Macao, America/Manaus, Africa/Freetown, Europe/Bucharest, Asia/Tomsk, America/Argentina/Mendoza, Asia/Macau, Europe/Malta, Mexico/BajaSur, Pacific/Tahiti, Africa/Asmera, Europe/Busingen, America/Argentina/Rio_Gallegos, Africa/Malabo, Europe/Skopje, America/Catamarca, America/Godthab, Europe/Sarajevo, Australia/ACT, GB-Eire, Africa/Lagos, America/Cordoba, Europe/Rome, Asia/Dacca, Indian/Mauritius, Pacific/Samoa, America/Regina, America/Fort_Wayne, America/Dawson_Creek, Africa/Algiers, Europe/Mariehamn, America/St_Johns, America/St_Thomas, Europe/Zurich, America/Anguilla, Asia/Dili, America/Denver, Africa/Bamako, Europe/Saratov, GB, Mexico/General, Pacific/Wallis, Europe/Gibraltar, Africa/Conakry, Africa/Lubumbashi, Asia/Istanbul, America/Havana, NZ-CHAT, Asia/Choibalsan, America/Porto_Acre, Asia/Omsk, Europe/Vaduz, US/Michigan, Asia/Dhaka, America/Barbados, Europe/Tiraspol, Atlantic/Cape_Verde, Asia/Yekaterinburg, America/Louisville, Pacific/Johnston, Pacific/Chatham, Europe/Ljubljana, America/Sao_Paulo, Asia/Jayapura, America/Curacao, Asia/Dushanbe, America/Guyana, America/Guayaquil, America/Martinique, Portugal, Europe/Berlin, Europe/Moscow, Europe/Chisinau, America/Puerto_Rico, America/Rankin_Inlet, Pacific/Ponape, Europe/Stockholm, Europe/Budapest, America/Argentina/Jujuy, Australia/Eucla, Asia/Shanghai, Universal, Europe/Zagreb, America/Port_of_Spain, Europe/Helsinki, Asia/Beirut, Asia/Tel_Aviv, Pacific/Bougainville, US/Central, Africa/Sao_Tome, Indian/Chagos, America/Cayenne, Asia/Yakutsk, Pacific/Galapagos, Australia/North, Europe/Paris, Africa/Ndjamena, Pacific/Fiji, America/Rainy_River, Indian/Maldives, Australia/Yancowinna, SystemV/AST4, Asia/Oral, America/Yellowknife, Pacific/Enderbury, America/Juneau, Australia/Victoria, America/Indiana/Vevay, Asia/Tashkent, Asia/Jakarta, Africa/Ceuta, Asia/Barnaul, America/Recife, America/Buenos_Aires, America/Noronha, America/Swift_Current, Australia/Adelaide, America/Metlakatla, Africa/Djibouti, America/Paramaribo, Europe/Simferopol, Europe/Sofia, Africa/Nouakchott, Europe/Prague, America/Indiana/Vincennes, Antarctica/Mawson, America/Kralendijk, Antarctica/Troll, Europe/Samara, Indian/Christmas, America/Antigua, Pacific/Gambier, America/Indianapolis, America/Inuvik, America/Iqaluit, Pacific/Funafuti, UTC, Antarctica/Macquarie, Canada/Pacific, America/Moncton, Africa/Gaborone, Pacific/Chuuk, Asia/Pyongyang, America/St_Vincent, Asia/Gaza, Etc/Universal, PST8PDT, Atlantic/Faeroe, Asia/Qyzylorda, Canada/Newfoundland, America/Kentucky/Louisville, America/Yakutat, Asia/Ho_Chi_Minh, Antarctica/Casey, Europe/Copenhagen, Africa/Asmara, Atlantic/Azores, Europe/Vienna, ROK, Pacific/Pitcairn, America/Mazatlan, Australia/Queensland, Pacific/Nauru, Europe/Tirane, Asia/Kolkata, SystemV/MST7, Australia/Canberra, MET, Australia/Broken_Hill, Europe/Riga, America/Dominica, Africa/Abidjan, America/Mendoza, America/Santarem, Kwajalein, America/Asuncion, Asia/Ulan_Bator, NZ, America/Boise, Australia/Currie, EST5EDT, Pacific/Guam, Pacific/Wake, Atlantic/Bermuda, America/Costa_Rica, America/Dawson, Asia/Chongqing, Eire, Europe/Amsterdam, America/Indiana/Knox, America/North_Dakota/Beulah, Africa/Accra, Atlantic/Faroe, Mexico/BajaNorte, America/Maceio, Etc/UCT, Pacific/Apia, GMT0, America/Atka, Pacific/Niue, Canada/East-Saskatchewan, Australia/Lord_Howe, Europe/Dublin, Pacific/Truk, MST7MDT, America/Monterrey, America/Nassau, America/Jamaica, Asia/Bishkek, America/Atikokan, Atlantic/Stanley, Australia/NSW, US/Hawaii, SystemV/CST6, Indian/Mahe, Asia/Aqtobe, America/Sitka, Asia/Vladivostok, Africa/Libreville, Africa/Maputo, Zulu, America/Kentucky/Monticello, Africa/El_Aaiun, Africa/Ouagadougou, America/Coral_Harbour, Pacific/Marquesas, Brazil/West, America/Aruba, America/North_Dakota/Center, America/Cayman, Asia/Ulaanbaatar, Asia/Baghdad, Europe/San_Marino, America/Indiana/Tell_City, America/Tijuana, Pacific/Saipan, SystemV/YST9, Africa/Douala, America/Chihuahua, America/Ojinaga, Asia/Hovd, America/Anchorage, Chile/EasterIsland, America/Halifax, Antarctica/Rothera, America/Indiana/Indianapolis, US/Mountain, Asia/Damascus, America/Argentina/San_Luis, America/Santiago, Asia/Baku, America/Argentina/Ushuaia, Atlantic/Reykjavik, Africa/Brazzaville, Africa/Porto-Novo, America/La_Paz, Antarctica/DumontDUrville, Asia/Taipei, Antarctica/South_Pole, Asia/Manila, Asia/Bangkok, Africa/Dar_es_Salaam, Poland, Atlantic/Madeira, Antarctica/Palmer, America/Thunder_Bay, Africa/Addis_Ababa, Asia/Yangon, Europe/Uzhgorod, Brazil/DeNoronha, Asia/Ashkhabad, Etc/Zulu, America/Indiana/Marengo, America/Creston, America/Punta_Arenas, America/Mexico_City, Antarctica/Vostok, Asia/Jerusalem, Europe/Andorra, US/Samoa, PRC, Asia/Vientiane, Pacific/Kiritimati, America/Matamoros, America/Blanc-Sablon, Asia/Riyadh, Iceland, Pacific/Pohnpei, Asia/Ujung_Pandang, Atlantic/South_Georgia, Europe/Lisbon, Asia/Harbin, Europe/Oslo, Asia/Novokuznetsk, CST6CDT, Atlantic/Canary, America/Knox_IN, Asia/Kuwait, SystemV/HST10, Pacific/Efate, Africa/Lome, America/Bogota, America/Menominee, America/Adak, Pacific/Norfolk, Europe/Kirov, America/Resolute, Pacific/Tarawa, Africa/Kampala, Asia/Krasnoyarsk, Greenwich, SystemV/EST5, America/Edmonton, Europe/Podgorica, Australia/South, Canada/Central, Africa/Bujumbura, America/Santo_Domingo, US/Eastern, Europe/Minsk, Pacific/Auckland, Africa/Casablanca, America/Glace_Bay, Canada/Eastern, Asia/Qatar, Europe/Kiev, Singapore, Asia/Magadan, SystemV/PST8, America/Port-au-Prince, Europe/Belfast, America/St_Barthelemy, Asia/Ashgabat, Africa/Luanda, America/Nipigon, Atlantic/Jan_Mayen, Brazil/Acre, Asia/Muscat, Asia/Bahrain, Europe/Vilnius, America/Fortaleza, Etc/GMT0, US/East-Indiana, America/Hermosillo, America/Cancun, Africa/Maseru, Pacific/Kosrae, Africa/Kinshasa, Asia/Kathmandu, Asia/Seoul, Australia/Sydney, America/Lima, Australia/LHI, America/St_Lucia, Europe/Madrid, America/Bahia_Banderas, America/Montserrat, Asia/Brunei, America/Santa_Isabel, Canada/Mountain, America/Cambridge_Bay, Asia/Colombo, Australia/West, Indian/Antananarivo, Australia/Brisbane, Indian/Mayotte, US/Indiana-Starke, Asia/Urumqi, US/Aleutian, Europe/Volgograd, America/Lower_Princes, America/Vancouver, Africa/Blantyre, America/Rio_Branco, America/Danmarkshavn, America/Detroit, America/Thule, Africa/Lusaka, Asia/Hong_Kong, Iran, America/Argentina/La_Rioja, Africa/Dakar, SystemV/CST6CDT, America/Tortola, America/Porto_Velho, Asia/Sakhalin, Etc/GMT+10, America/Scoresbysund, Asia/Kamchatka, Asia/Thimbu, Africa/Harare, Etc/GMT+12, Etc/GMT+11, Navajo, America/Nome, Europe/Tallinn, Turkey, Africa/Khartoum, Africa/Johannesburg, Africa/Bangui, Europe/Belgrade, Jamaica, Africa/Bissau, Asia/Tehran, WET, Europe/Astrakhan, Africa/Juba, America/Campo_Grande, America/Belem, Etc/Greenwich, Asia/Saigon, America/Ensenada, Pacific/Midway, America/Jujuy, Africa/Timbuktu, America/Bahia, America/Goose_Bay, America/Virgin, America/Pangnirtung, Asia/Katmandu, America/Phoenix, Africa/Niamey, America/Whitehorse, Pacific/Noumea, Asia/Tbilisi, America/Montreal, Asia/Makassar, America/Argentina/San_Juan, Hongkong, UCT, Asia/Nicosia, America/Indiana/Winamac, SystemV/MST7MDT, America/Argentina/ComodRivadavia, America/Boa_Vista, America/Grenada, Asia/Atyrau, Australia/Darwin, Asia/Khandyga, Asia/Kuala_Lumpur, Asia/Famagusta, Asia/Thimphu, Asia/Rangoon, Europe/Bratislava, Asia/Calcutta, America/Argentina/Tucuman, Asia/Kabul, Indian/Cocos, Japan, Pacific/Tongatapu, America/New_York, Etc/GMT-12, Etc/GMT-11, Etc/GMT-10, SystemV/YST9YDT, Europe/Ulyanovsk, Etc/GMT-14, Etc/GMT-13, W-SU, America/Merida, EET, America/Rosario, Canada/Saskatchewan, America/St_Kitts, Arctic/Longyearbyen, America/Fort_Nelson, America/Caracas, America/Guadeloupe, Asia/Hebron, Indian/Kerguelen, SystemV/PST8PDT, Africa/Monrovia, Asia/Ust-Nera, Egypt, Asia/Srednekolymsk, America/North_Dakota/New_Salem, Asia/Anadyr, Australia/Melbourne, Asia/Irkutsk, America/Shiprock, America/Winnipeg, Europe/Vatican, Asia/Amman, Etc/UTC, SystemV/AST4ADT, Asia/Tokyo, America/Toronto, Asia/Singapore, Australia/Lindeman, America/Los_Angeles, SystemV/EST5EDT, Pacific/Majuro, America/Argentina/Buenos_Aires, Europe/Nicosia, Pacific/Guadalcanal, Europe/Athens, US/Pacific, Europe/Monaco]

Get your JVM’s current default time zone.

ZoneId z = ZoneId.systemDefault() ; 

America/Los_Angeles

Be aware that the JVM's default can be changed at any moment during runtime by any code in any thread of any app within the JVM. Generally better to specify the desired/expected time zone rather than rely on system default.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;

If you want to know the offset in play at a particular moment for a particular zone, ask via the ZoneRules object.

ZoneOffset offsetInEffectNow = z.getRules().getOffset( Instant.now() );

See all the above code run live at IdeOne.com.

The bottom line is - can't rely on ID strings, must go with the offset as display ID's may vary from system to system.

No, time zone identifiers are documented and consistent. See this list in Wikipedia tracked by the IANA.

I do not know much about what TimeZone was doing, but if like the rest of the legacy date-time classes, it may not be wisely designed. Also not sure how your host OS and JVM was configured. Hard to diagnose as you did not provide enough information.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
    • See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

🌐
Oracle
docs.oracle.com › javase › 8 › docs › api › java › util › TimeZone.html
TimeZone (Java Platform SE 8 )
2 weeks ago - Java™ Platform Standard Ed. 8 ... TimeZone represents a time zone offset, and also figures out daylight savings.
🌐
Medium
medium.com › @davoud.badamchi › tackling-timezones-in-java-a-comprehensive-guide-for-developers-5bad69b2c079
Tackling Timezones in Java: A Comprehensive Guide for Developers | by Davoud Badamchi | Medium
July 3, 2024 - When developing applications that handle date and time, it is essential to use timezone-aware classes provided by the java.time package. Here are some best practices: Always Use ZonedDateTime or OffsetDateTime for Timezone Awareness:
Find elsewhere
🌐
Jenkov
jenkov.com › tutorials › java-date-time › java-util-timezone.html
Java's java.util.TimeZone
June 23, 2014 - The Java TimeZone class is a class that represents time zones, and is helpful when doing calendar arithmetics across time zones.
🌐
Wikipedia
en.wikipedia.org › wiki › List_of_tz_database_time_zones
List of tz database time zones - Wikipedia
2 weeks ago - Historical data for such zones is still preserved in the source code, but it is not included when compiling the database with standard options. Standard Time (SDT) and Daylight Saving Time (DST) offsets from UTC in hours and minutes.
🌐
Microsoft Learn
learn.microsoft.com › en-us › java › openjdk › timezones
Configure timezones in Java | Microsoft Learn
January 8, 2025 - The following example configures the container to use the America/New_York timezone by setting the TZ environment variable and installing the tzdata package: # Use a base image with Java installed FROM mcr.microsoft.com/openjdk/jdk:21-mariner # Set the timezone environment variable ENV TZ=America/New_York # Set the working directory WORKDIR /app # Copy the application JAR file to the container COPY myapp.jar /app/myapp.jar # Run the application CMD ["java", "-jar", "myapp.jar"]
🌐
Joda
joda.org › joda-time › timezones.html
Joda-Time – Java date and time API - Time Zones
Time zone data is provided by globa-tz which is derived from the standard IANA tz database, but global-tz reinstates data that was inappropriately removed. The following table shows the time zones supported by Joda-Time, using version 2025a of the database. Note that Joda-Time's time zone database ...
Top answer
1 of 16
535

tl;dr

Instant.now()   // Capture the current moment in UTC. 

Generate a String to represent that value:

Instant.now().toString()  

2016-09-13T23:30:52.123Z

Details

As the correct answer by Jon Skeet stated, a java.util.Date object has no time zone. But its toString implementation applies the JVM’s default time zone when generating the String representation of that date-time value. Confusingly to the naïve programmer, a Date seems to have a time zone but does not.

The java.util.Date, j.u.Calendar, and java.text.SimpleDateFormat classes bundled with Java are notoriously troublesome. Avoid them. Instead, use either of these competent date-time libraries:

  • java.time.* package in Java 8
  • Joda-Time

java.time (Java 8)

Java 8 brings an excellent new java.time.* package to supplant the old java.util.Date/Calendar classes.

Getting current time in UTC/GMT is a simple one-liner…

Instant instant = Instant.now();

That Instant class is the basic building block in java.time, representing a moment on the timeline in UTC with a resolution of nanoseconds.

In Java 8, the current moment is captured with only up to milliseconds resolution. Java 9 brings a fresh implementation of Clock captures the current moment in up to the full nanosecond capability of this class, depending on the ability of your host computer’s clock hardware.

toString method of Instant generates a String representation of its value using one specific ISO 8601 format. That format outputs zero, three, six or nine digits digits (milliseconds, microseconds, or nanoseconds) as necessary to represent the fraction-of-second.

If you want more flexible formatting, or other additional features, then apply an offset-from-UTC of zero, for UTC itself (ZoneOffset.UTC constant) to get a OffsetDateTime.

OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC );

Dump to console…

System.out.println( "now.toString(): " + now );

When run…

now.toString(): 2014-01-21T23:42:03.522Z

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
  • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
  • Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
  • Later versions of Android bundle implementations of the java.time classes.
  • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.


Joda-Time

UPDATE: The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

Using the Joda-Time 3rd-party open-source free-of-cost library, you can get the current date-time in just one line of code.

Joda-Time inspired the new java.time.* classes in Java 8, but has a different architecture. You may use Joda-Time in older versions of Java. Joda-Time continues to work in Java 8 and continues to be actively maintained (as of 2014). However, the Joda-Time team does advise migration to java.time.

System.out.println( "UTC/GMT date-time in ISO 8601 format: " + new org.joda.time.DateTime( org.joda.time.DateTimeZone.UTC ) );

More detailed example code (Joda-Time 2.3)…

org.joda.time.DateTime now = new org.joda.time.DateTime(); // Default time zone.
org.joda.time.DateTime zulu = now.toDateTime( org.joda.time.DateTimeZone.UTC );

Dump to console…

System.out.println( "Local time in ISO 8601 format: " + now );
System.out.println( "Same moment in UTC (Zulu): " + zulu );

When run…

Local time in ISO 8601 format: 2014-01-21T15:34:29.933-08:00
Same moment in UTC (Zulu): 2014-01-21T23:34:29.933Z

For more example code doing time zone work, see my answer to a similar question.

Time Zone

I recommend you always specify a time zone rather than relying implicitly on the JVM’s current default time zone (which can change at any moment!). Such reliance seems to be a common cause of confusion and bugs in date-time work.

When calling now() pass the desired/expected time zone to be assigned. Use the DateTimeZone class.

DateTimeZone zoneMontréal = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zoneMontréal );

That class holds a constant for UTC time zone.

DateTime now = DateTime.now( DateTimeZone.UTC );

If you truly want to use the JVM’s current default time zone, make an explicit call so your code is self-documenting.

DateTimeZone zoneDefault = DateTimeZone.getDefault();

ISO 8601

Read about ISO 8601 formats. Both java.time and Joda-Time use that standard’s sensible formats as their defaults for both parsing and generating strings.


Actually, java.util.Date does have a time zone, buried deep under layers of source code. For most practical purposes, that time zone is ignored. So, as shorthand, we say java.util.Date has no time zone. Furthermore, that buried time zone is not the one used by Date’s toString method; that method uses the JVM’s current default time zone. All the more reason to avoid this confusing class and stick with Joda-Time and java.time.

2 of 16
445

java.util.Date has no specific time zone, although its value is most commonly thought of in relation to UTC. What makes you think it's in local time?

To be precise: the value within a java.util.Date is the number of milliseconds since the Unix epoch, which occurred at midnight January 1st 1970, UTC. The same epoch could also be described in other time zones, but the traditional description is in terms of UTC. As it's a number of milliseconds since a fixed epoch, the value within java.util.Date is the same around the world at any particular instant, regardless of local time zone.

I suspect the problem is that you're displaying it via an instance of Calendar which uses the local timezone, or possibly using Date.toString() which also uses the local timezone, or a SimpleDateFormat instance, which, by default, also uses local timezone.

If this isn't the problem, please post some sample code.

I would, however, recommend that you use Joda-Time anyway, which offers a much clearer API.

🌐
Baeldung
baeldung.com › home › java › java dates › display all time zones with gmt and utc in java
Display All Time Zones With GMT and UTC in Java | Baeldung
March 17, 2024 - Time zones in UTC: (UTC+14:00) Pacific/Apia (UTC+14:00) Pacific/Kiritimati (UTC+14:00) Pacific/Tongatapu (UTC+14:00) Etc/GMT-14 · Java 8 makes this task easier by using the Stream and Date and Time APIs.
Top answer
1 of 1
15

Time zones are frequently redefined by politicians. New zones appear. Old ones get renamed (ex: Asia/Kolkata). Some are determined to not actually be distinct, and end up pointing to another (ex: America/Montreal). And that is just the names – the offsets within each zone are also often modified by politicians for anomalies such as Daylight Saving Time (DST), or deciding to get off DST altogether or deciding to stay on DST all-year-round or deciding to change the offset by 15 minutes to make some political statement such as distinguishing yourself from your neighboring countries. So there is no simple permanent list.

Java comes with a copy of the tzdata time zone database. If any zones you care about experience a change, you need to update this tzdata in your Java installations. Oracle provides a tool for this chore in their implementation; I do not know about others. Similarly you should also update the tzdata in your host computer’s OS as well as other utilities such as your database like Postgres.

As for references to a ZoneId object in Java, you may define some as constants. The java.time classes are thread-safe. So you may keep a single instance around as a constant.

public class TimeUtils {
    static public ZoneId ZONEID_EUROPE_PARIS = ZoneId.of( "Europe/Paris" ) ;
    static public ZoneId ZONEID_ASIA_KOLKATA = ZoneId.of( "Asia/Kolkata" ) ;
}

You have a LocalDateTime representing potential moments, not a specific point on the timeline. A LocalDateTime has no time zone or offset information. So a LocalDateTime of noon June 1 this year could mean many different moments, with the first noon happening in Kiribati where the time zone has an offset fourteen hours ahead of UTC. Noon in Bangladesh comes later, and noon in Paris France still hours later. So a LocalDateTime has no real meaning until you apply a time zone for context.

LocalDateTime noon1June2017Anywhere = LocalDateTime.of( 2017 , Month.JUNE , 1 , 12 , 0);

Use those constants where you need a ZoneId.

ZonedDateTime noon1June2017EuropeParis = noon1June2017Anywhere.atZone( TimeUtils.ZONEID_EUROPE_PARIS ) ;
ZonedDateTime noon1June2017AsiaKolkata = noon1June2017Anywhere.atZone( TimeUtils.ZONEID_ASIA_KOLKATA ) ;

Note that noon1June2017EuropeParis and noon1June2017AsiaKolkata are two different moments, different points on the timeline. Noon happens much earlier in India than it does in France.

Let's see those two values in UTC as Instant objects. These two Instant objects are not equal, as the Kolkata one is several hours earlier than the Paris one.

Instant instantNoon1June2017EuropeParis = noon1June2017EuropeParis.toInstant() ;  // Extract the same moment but in UTC zone.
Instant instantNoon1June2017AsiaKolkata = noon1June2017AsiaKolkata.toInstant() ; // Extract the same moment but in UTC zone.

Externalize

If the intent of your Question is to externalize the decision of what zone to apply, so that you may change that choice without recompiling your source code again, simply store a string of the zone name such as Europe/Paris as a string in some external resource.

Pass your string to ZoneId.of.

ZoneId z = ZoneId.of( someStringOfZoneName ) ;

Possible storage mechanisms commonly used by folks:

  • Store the text in a file.
  • Store the text in a database row to retrieved by your app.
  • Store the text as an entry in a JNDI facility (LDAP server, a configuration file in your Servlet container, etc.) (see Tutorial)
  • Query from a Web Service. (See Tutorial)
  • Ask the user for their preference and store in a variable such as a member of a class, or in a Servlet environment store string as an attribute on the context object or on the session object. You can provide the user with a choice list of all zones by calling ZoneId.getAvailableZoneIds.

You can ask for the JVM’s current default zone: ZoneId.systemDefault. But beware, this can be changed at anytime by any code in any app in that JVM.

Top answer
1 of 3
5

Java 8 uses IANA timezones names (always in the format Region/City, like America/Sao_Paulo or Europe/Berlin). Avoid using the short abbreviations (like CEST or PST) because they are ambiguous and not standard.

Actually, those names don't work with ZoneId mainly because of this ambiguity (CST, for example, can be "Central Standard Time", "Cuba Standard Time" or "China Standard Time"). Actually, some of them might work due to retro-compatibility reasons, but it's not guaranteed to work with all of them.

I'm assuming that CEST is the Central European Summer Time. There are lots of different countries (and timezones) that are currently in CEST, so the API can't decide which timezone to choose if you just pass "CEST" to it.

That's because a timezone contains all the different offsets a region had during its history. There may be lots of countries using CEST today, but their history differs in the past (some might had DST in different years, or used a different offset and then changed, etc), and that's why they have one timezone for each.

To use such short names (like CEST), though, you can define some defaults for each one (which will be an arbitrary choice) and put these choices in a map:

// map of custom zone names
Map<String, String> map = new HashMap<>();
// setting my arbitrary choices for each name
map.put("CEST", "Europe/Berlin"); // Berlin during DST period
map.put("CET", "Europe/Berlin"); // Berlin during non-DST period
// ... and so on

Then you can use this map to create the ZoneId:

// use the custom map to create the ZoneId
ZoneId zoneFrom = ZoneId.of(tzFrom, map);
...
// use the custom map to create the ZoneId
ZonedDateTime rezDate = dateAndTimeINeed.withZoneSameInstant(ZoneId.of(tzTo, map));

I've chosen Europe/Berlin, but of course you can change it to whatever timezone you need. You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds().


Using the map above:

System.out.println(changeTZ("CEST", "UTC", "2017-08-10 14:23:58"));

This code outputs:

2017-08-10 12:23:58

Note that 14:23 in CEST (which I chose to be Europe/Berlin) is 12:23 in UTC, which is correct because in August Berlin is in DST (offset is +02:00).

ZoneId and ZonedDateTime classes handle DST effects automatically. You can check this by choosing a date in January (when DST is not in effect in Berlin):

// January is not DST, so use CET
System.out.println(changeTZ("CET", "UTC", "2017-01-10 14:23:58"));

The output is:

2017-01-10 13:23:58

In January Berlin is not in DST, so the offset is +01:00, then 14:23 in Berlin becomes 13:23 in UTC.


Of course the ideal is to always use the full names (like Europe/Berlin), but the custom map is an alternative if you don't have control over the inputs.

Java 8 also has a built-in predefined map, but as any other predefined stuff, the choices are arbitrary and not necessarily the ones you need.

2 of 3
5

This solution uses the IANA timezones names mentioned by Hugo in the comments to get the ZoneId (more details here). Will throw an exception if you use it with CEST.

public static String changeTZ(String tzFrom, String tzTo, String dateToChange){
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of(tzFrom));
    ZonedDateTime zdt = ZonedDateTime.parse(dateToChange, dtf);
    DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of(tzTo));  
    return zdt.format(dtf2);
}

Use like:

String rez = changeTZ("US/Alaska", "Europe/Berlin", "2017-08-10 14:23:58");
🌐
Azul
azul.com › home › blog › time zone and currency database in jdk
Time Zone and Currency Database in JDK - Azul | Better Java Performance, Superior Java Support
April 15, 2025 - Why do we need a new version of the time zone and currency database every few months? Let's find out... Within the Java code, a whole list of time zones is defined. We can get this list quickly in jshell.
🌐
GitHub
github.com › openjdk › jdk › blob › master › src › java.base › share › classes › java › util › TimeZone.java
jdk/src/java.base/share/classes/java/util/TimeZone.java at master · openjdk/jdk
* for multiple time zones (for example, "CST" could be U.S. "Central Standard · * Time" and "China Standard Time"), and the Java platform can then only · * recognize one of them. The full list of deprecated three-letter time · * zone IDs and their mappings can be viewed at {@link java.time.ZoneId#SHORT_IDS}. * * @see Calendar ·
Author   openjdk
Top answer
1 of 9
26

The list of timezones is very application and locale specific. Only you know what zones are most applicable to your users. We actually have different lists for different regions.

Here is our list for US users for your reference,

    "Pacific/Midway",
    "US/Hawaii",
    "US/Alaska",
    "US/Pacific",
    "America/Tijuana",
    "US/Arizona",
    "America/Chihuahua",
    "US/Mountain",
    "America/Guatemala",
    "US/Central",
    "America/Mexico_City",
    "Canada/Saskatchewan",
    "America/Bogota",
    "US/Eastern",
    "US/East-Indiana",
    "Canada/Eastern",
    "America/Caracas",
    "America/Manaus",
    "America/Santiago",
    "Canada/Newfoundland",
    "Brazil/East",
    "America/Buenos_Aires",
    "America/Godthab",
    "America/Montevideo",
    "Atlantic/South_Georgia",
    "Atlantic/Azores",
    "Atlantic/Cape_Verde",
    "Africa/Casablanca",
    "Europe/London",
    "Europe/Berlin",
    "Europe/Belgrade",
    "Europe/Brussels",
    "Europe/Warsaw",
    "Africa/Algiers",
    "Asia/Amman",
    "Europe/Athens",
    "Asia/Beirut",
    "Africa/Cairo",
    "Africa/Harare",
    "Europe/Helsinki",
    "Asia/Jerusalem",
    "Europe/Minsk",
    "Africa/Windhoek",
    "Asia/Baghdad",
    "Asia/Kuwait",
    "Europe/Moscow",
    "Africa/Nairobi",
    "Asia/Tbilisi",
    "Asia/Tehran",
    "Asia/Muscat",
    "Asia/Baku",
    "Asia/Yerevan",
    "Asia/Kabul",
    "Asia/Yekaterinburg",
    "Asia/Karachi",
    "Asia/Calcutta",
    "Asia/Colombo",
    "Asia/Katmandu",
    "Asia/Novosibirsk",
    "Asia/Dhaka",
    "Asia/Rangoon",
    "Asia/Bangkok",
    "Asia/Krasnoyarsk",
    "Asia/Hong_Kong",
    "Asia/Irkutsk",
    "Asia/Kuala_Lumpur",
    "Australia/Perth",
    "Asia/Taipei",
    "Asia/Tokyo",
    "Asia/Seoul",
    "Asia/Yakutsk",
    "Australia/Adelaide",
    "Australia/Darwin",
    "Australia/Brisbane",
    "Australia/Sydney",
    "Pacific/Guam",
    "Australia/Hobart",
    "Asia/Vladivostok",
    "Asia/Magadan",
    "Pacific/Auckland",
    "Pacific/Fiji",
    "Pacific/Tongatapu",
2 of 9
12

I've just written a small Java utility that provides a list of Windows time zones (the zones in the time zone selection dialog in Windows), and their associated Java TimeZone objects. See https://github.com/nfergu/Java-Time-Zone-List

This is based on the CLDR mappings at http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml

🌐
Microsoft Learn
learn.microsoft.com › en-us › dotnet › api › java.util.timezone
TimeZone Class (Java.Util) | Microsoft Learn
TimeZone represents a time zone offset, and also figures out daylight savings. [Android.Runtime.Register("java/util/TimeZone", DoNotGenerateAcw=true)] public abstract class TimeZone : Java.Lang.Object, IDisposable, Java.Interop.IJavaPeerable, Java.IO.ISerializable, Java.Lang.ICloneable
🌐
Reddit
reddit.com › r/javahelp › how do i hard code a time with time zone?
r/javahelp on Reddit: How do I hard code a time with time zone?
February 23, 2022 -

How do I create this variable in Java?

businessOpenTime = 8:00 am US Eastern time

All I can find so far is converting local time to zoned date times and strings to zoned date time, but I simply want to hardcode a time with time zone. Thank you

Top answer
1 of 3
3
It's interesting because there is actually no zoned time type for some reason. Maybe there's a good reason for it and someone can explain why not. The closest we have is OffsetTime, but this is obviously just an offset so won't cater for daylight savings, unless if you get the offset for the zone at that specific point in time. Actually after writing that I now understand why there's no zoned time, because a zoned time is really the time at the specified date at the specified time zone (the offset changes depending on whether we're in daylight savings or not). Which would make it a ZonedDateTime. So anyway to answer your question, your options are: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/OffsetTime.html#of(java.time.LocalTime,java.time.ZoneOffset) Or https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/ZonedDateTime.html#of(java.time.LocalDateTime,java.time.ZoneId) Where ZoneId is ZoneId.of("America/New_York") Edit: Or u/morhp 's suggestion to store it as 2 fields (LocalTime, ZoneId) and figure out the opening time for today's date on demand.
2 of 3
3
The classes Java has typically store a fixed time or date (or both). For example OffsetTime is always something like 10:15:30+01:00, so it's the same time each day. Something like a ZonedTime isn't really fixed, as the "real time" depends on if daylight saving is active or not. There's nothing wrong with creating a simple class/record yourself that stores a LocalTime together with a ZoneId if you need that. (However it probably makes more sense to store the time zone on your business and then just use LocalTime objects for opening/closing hours)
🌐
MoldStud
moldstud.com › articles › developers faq › core java developers questions › mastering java dates and time best practices for avoiding time zone pitfalls
Mastering Java Dates and Time Best Practices for Avoiding Time Zone Pitfalls | MoldStud
October 17, 2024 - When working with dates and times, it is essential to consider the time zone to ensure accurate calculations and display to end users in different regions. Java provides the ZoneId class to represent a time zone, and developers can use it to ...