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 conver
ZoneIdThe TimeZone class is now legacy, supplanted years ago by the modern java.time classes defined in JSR 310. Specifically replaced by java.time.ZoneId.
Most of the currently used time zones are in the name format of Continent/Region. See a sortable list at Wikipedia.
Get a list of all the time zone names.
Set zoneIds = ZoneId.getAvailableZoneIds() ;
System.out.println( "zoneIds = " + zoneIds );
See a distinct list of those prefixes.
zoneIds.stream().map( s -> s.split( "/" )[0] ).collect( Collectors.toSet()).stream().forEach( System.out::println );
As mentioned in the Answer by tbruyelle, one way to narrow the list for presentation to the user is to filter on that Continent portion. Of those, I would guess it best to focus on:
…plus add Etc/UTC.
In Java code, sorted alphabetically.
List < String > zoneGroupNames = List.of(
"Africa" ,
"Antarctica" ,
"Atlantic" ,
"America" ,
"Australia" ,
"Europe" ,
"Indian" ,
"Pacific" ,
"UTC"
);
Build a Map of each zone group name to collection of zone id names. We need a map of the group name such as Europe to a list of the zone names such as Europe/Berlin, Europe/London, and Europe/Malta.
Map < String, List < String > > mapGroupNameToZoneNames = new TreeMap <>();
Mapping a key to a collection of values is known as a "multimap". We now have built-in multimap functionality with the Map implementations bundled with Java. Call Map::computeIfAbsent (see this Answer).
Set < String > zoneIdStrings = ZoneId.getAvailableZoneIds();
for ( String zoneIdString : zoneIdStrings )
{
String groupName = zoneIdString.split( "/" )[ 0 ];
if ( zoneGroupNames.contains( groupName ) )
{
mapGroupNameToZoneNames.computeIfAbsent( groupName , ( x -> new ArrayList <>() ) ).add( zoneIdString );
} // Else skip it.
}
System.out.println( "mapGroupNameToZoneNames = " + mapGroupNameToZoneNames );
Present that list of groups to the user. Say the user selects item # 6 (index 5), which is currently Europe.
String groupNameChosenByUser = zoneGroupNames.get( 5 ); // Europe
List < String > zoneNamesOfGroup = mapGroupNameToZoneNames.get( groupNameChosenByUser );
Present that list of zone names for that one group. Say the user selects item # 12 (index 11), which is currently Europe/Malta.
String zoneNameChosenByUser = zoneNamesOfGroup.get( 11 ); // Malta
Make a ZoneId object from the string of that zone name.
ZoneId zoneIdChosenByUser = ZoneId.of( zoneNameChosenByUser );
zoneIdChosenByUser.toString() = Europe/Malta