TimeZones in Java

后端 未结 9 1341
执念已碎
执念已碎 2020-12-03 07:19

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

9条回答
  •  误落风尘
    2020-12-03 07:30

    ZoneId

    The 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:

    • Europe
    • Africa
    • Antarctica
    • Atlantic
    • America
    • Pacific
    • Indian
    • Australia

    …plus add Etc/UTC.

    In Java code, sorted alphabetically.

    List < String > zoneGroupNames = List.of(
            "Africa" ,
            "Antarctica" ,
            "Atlantic" ,
            "America" ,
            "Australia" ,
            "Europe" ,
            "Indian" ,
            "Pacific" ,
            "UTC"
    );
    

    Multimap of zone group name to zone names

    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 to user

    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

提交回复
热议问题