Sorting TimeZone

Discussion in 'Java' started by Wojtek, Nov 3, 2009.

  1. Wojtek

    Wojtek Guest

    How would you sort timezones?

    I am trying to sort them according to their offset from UTC. I cannot
    use a TreeMap because there are many timezones with the same offset,
    which of course over-writes the previously put timezone.

    The preferred sort would be offset, then display name.

    --
    Wojtek :)
    Wojtek, Nov 3, 2009
    #1
    1. Advertising

  2. Wojtek

    markspace Guest

    Wojtek wrote:
    > How would you sort timezones?
    >
    > I am trying to sort them according to their offset from UTC. I cannot
    > use a TreeMap because there are many timezones with the same offset,
    > which of course over-writes the previously put timezone.
    >
    > The preferred sort would be offset, then display name.
    >



    I guess put them all in an array, the use Array.sort( Object[],
    Comparator<T>) to sort them as you desire.
    markspace, Nov 3, 2009
    #2
    1. Advertising

  3. Wojtek

    Wojtek Guest

    markspace wrote :
    > Wojtek wrote:
    >> How would you sort timezones?
    >>
    >> I am trying to sort them according to their offset from UTC. I cannot use a
    >> TreeMap because there are many timezones with the same offset, which of
    >> course over-writes the previously put timezone.
    >>
    >> The preferred sort would be offset, then display name.
    >>

    >
    >
    > I guess put them all in an array, the use Array.sort( Object[],
    > Comparator<T>) to sort them as you desire.


    Yes, I made my own custom Comparator.

    But I just found out what the problem is. You can retrieve a TimeZone
    using a variety of names, but that TimeZone only has one display name.
    For instance, in Canada:

    Canada/Newfoundland Newfoundland Standard Time
    Canada/Atlantic Atlantic Standard Time
    Canada Eastern Eastern Standard Time
    Canada/Central Central Standard Time *
    Canada/East-Saskatchewan Central Standard Time *
    Canada/Saskatchewan Central Standard Time *
    Canada/Mountain Mountain Standard Time
    Canada/Pacific Pacific Standard Time *
    Canada/Yukon Pacific Standard Time *

    I retrieve them using the left names, but the .getDisplayName() returns
    the right side. Which throws the sorting out.

    Ok, I can make this work. Funny how actually _asking_ a question can
    lead to an answer...

    --
    Wojtek :)
    Wojtek, Nov 3, 2009
    #3
  4. Wojtek

    markspace Guest

    Wojtek wrote:
    > How would you sort timezones?
    >
    > I am trying to sort them according to their offset from UTC. I cannot
    > use a TreeMap because there are many timezones with the same offset,
    > which of course over-writes the previously put timezone.
    >
    > The preferred sort would be offset, then display name.
    >



    /*
    * To change this template, choose Tools | Templates
    * and open the template in the editor.
    */

    package sorttimezone;

    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.TimeZone;

    /**
    *
    * @author Brenden
    */
    public class Main {

    /**
    * @param args the command line arguments
    */
    public static void main(String[] args) {
    // TODO code application logic here
    String [] zonesIDs = TimeZone.getAvailableIDs();
    TimeZone [] allTZ = new TimeZone[zonesIDs.length];
    for( int i=0; i< allTZ.length; i++ ) {
    allTZ=TimeZone.getTimeZone( zonesIDs );
    }
    Arrays.sort( allTZ, new SortByOffsetAndName() );

    for( TimeZone zone : allTZ ) {
    System.out.println( zone.getDisplayName() + ": "+
    zone.getRawOffset()/1000/60/60 );
    }
    }
    }

    class SortByOffsetAndName implements Comparator<TimeZone> {

    public int compare( TimeZone o1, TimeZone o2 )
    {
    if( o1.getRawOffset() != o2.getRawOffset() ) {
    return o1.getRawOffset() - o2.getRawOffset();
    }
    return o1.getDisplayName().compareTo( o2.getDisplayName() );
    }

    }
    markspace, Nov 3, 2009
    #4
  5. Wojtek

    markspace Guest

    Wojtek wrote:

    > I retrieve them using the left names, but the .getDisplayName() returns
    > the right side. Which throws the sorting out.
    >


    Instead of using getDisplayName() (which was the same thing I did, in my
    example I posted), use getID(), that returns the string on the left in
    your table.

    public int compare( TimeZone o1, TimeZone o2 )
    {
    if( o1.getRawOffset() != o2.getRawOffset() ) {
    return o1.getRawOffset() - o2.getRawOffset();
    }
    return o1.getID().compareTo( o2.getID() );
    }


    > Ok, I can make this work. Funny how actually _asking_ a question can
    > lead to an answer...



    It works that way for pretty much everyone. ;)
    markspace, Nov 3, 2009
    #5
  6. Wojtek

    Lew Guest

    Wojtek wrote:
    > How would you sort timezones?


    Do you mean 'java.util.TimeZone'?

    > I am trying to sort them according to their offset from UTC. I cannot
    > use a TreeMap because there are many timezones with the same offset,
    > which of course over-writes the previously put timezone.


    There's no "of course" about that if you are using your "preferred sort".

    Why would you use any kind of 'Map' rather than a 'Collection'?

    > The preferred sort would be offset, then display name.


    'TimeZone' can easily be a map key, yes, even for a 'TreeMap'. I fail to see
    the problem. You simply compare based on your "preferred sort".

    I'd be more concerned about relocation of a key when the offset changes for
    DST. But perhaps you're only building this structure for a given moment in
    time and that isn't a concern for you.

    Regardless, here's uncompiled, off-the-cuff code, using a 'Set' instead of a
    'Map':

    public class SortedZone
    {
    private long ref = System.currentTimeMillis();

    private final TreeSet <TimeZone> zones =
    new TreeSet <TimeZone>
    ( new Comparator <TimeZone> ()
    {
    @Override public int compare( TimeZone t0, TimeZone t1 )
    {
    return
    (t0 == null? (t1 == null? 0: -1)
    : t1 == null? 1
    : t0.getOffset( ref ) > t1.getOffset( ref )? 1
    : t0.getOffset( ref ) < t1.getOffset( ref )? -1
    : t0.getDisplayName().compareTo( t1.getDisplayName() )
    );
    }
    }
    );

    // cover methods for the Set ...
    }

    --
    Lew
    Lew, Nov 3, 2009
    #6
  7. Wojtek

    Roedy Green Guest

    On Mon, 02 Nov 2009 16:09:42 -0800, Wojtek <> wrote,
    quoted or indirectly quoted someone who said :

    >
    >I am trying to sort them according to their offset from UTC. I cannot
    >use a TreeMap because there are many timezones with the same offset,
    >which of course over-writes the previously put timezone.
    >
    >The preferred sort would be offset, then display name.


    I would create my own TimeZone Object with the fields I need then cook
    up a Comparable/Comparator for it.

    see http://mindprod.com/applet/comparatorcutter.html
    to generate the code.
    --
    Roedy Green Canadian Mind Products
    http://mindprod.com

    An example (complete and annotated) is worth 1000 lines of BNF.
    Roedy Green, Nov 3, 2009
    #7
  8. Wojtek

    Lew Guest

    Wojtek quoted or indirectly quoted someone who said :
    >> I am trying to sort them according to their offset from UTC. I cannot
    >> use a TreeMap because there are many timezones with the same offset,
    >> which of course over-writes the previously put timezone.
    >>
    >> The preferred sort would be offset, then display name.


    Roedy Green wrote:
    > I would create my own TimeZone Object with the fields I need then cook
    > up a Comparable/Comparator for it.


    Wojtek was speaking of java.util.TimeZone, judging by the fields he mentioned.

    --
    Lew
    Lew, Nov 3, 2009
    #8
  9. Wojtek

    Wojtek Guest

    Lew wrote :
    > 'TimeZone' can easily be a map key, yes, even for a 'TreeMap'.


    No it cannot be used as a key. It does not have a 'compareTo' method.

    --
    Wojtek :)
    Wojtek, Nov 3, 2009
    #9
  10. Wojtek

    Lew Guest

    Lew, Nov 3, 2009
    #10
  11. Wojtek

    Wojtek Guest

    Lew wrote :
    > Lew wrote :
    >>> 'TimeZone' can easily be a map key, yes, even for a 'TreeMap'.

    >>

    >
    > Wojtek wrote:
    >> No it cannot be used as a key. It does not have a 'compareTo' method.
    >>

    >
    > Yes, it can be used as a key!
    > <http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html#TreeMap
    > (java.util.Comparator)>
    >
    > The Javadocs are your friend.


    Yes with a separate Comparator. However you cannot do:

    TreeMap<TimeZone,String>

    directly.

    --
    Wojtek :)
    Wojtek, Nov 3, 2009
    #11
  12. Wojtek

    Lew Guest

    Lew wrote :
    >>>> 'TimeZone' can easily be a map key, yes, even for a 'TreeMap'.

    >


    Wojtek wrote:
    > >> No it cannot be used as a key. It does not have a 'compareTo' method.

    >


    Lew wrote:
    >> Yes, it can be used as a key!
    >> <http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html#TreeMap
    >> (java.util.Comparator)>

    >
    >> The Javadocs are your friend.

    >


    Wojtek wrote:
    > Yes with a separate Comparator. However you cannot do:
    >
    > TreeMap<TimeZone,String>
    >
    > directly.
    >


    Why doesn't

    Map <TimeZone, String> map =
    new TreeMap <TimeZone, String> ( new Comparator() { .... } );

    work for you?

    --
    Lew
    Lew, Nov 3, 2009
    #12
  13. Wojtek

    Lew Guest

    Lew wrote:
    > Why doesn't
    >
    >   Map <TimeZone, String> map =
    >     new TreeMap <TimeZone, String> ( new Comparator() { .... } );
    >
    > work for you?


    Oops. Naturally I meant to write

    Map <TimeZone, String> map =
    new TreeMap <TimeZone, String> ( new Comparator <TimeZone> ()
    { .... } );

    --
    Lew
    Lew, Nov 3, 2009
    #13
  14. Wojtek

    Wojtek Guest

    Lew wrote :
    > Lew wrote:
    >
    > Oops. Naturally I meant to write
    >
    > Map <TimeZone, String> map =
    > new TreeMap <TimeZone, String> ( new Comparator <TimeZone> ()
    > { .... } );


    No arguments that this does work.

    However I was replying to your statement "'TimeZone' can easily be a
    map key, yes, even for a 'TreeMap'. " which appears to say that you do
    not need a custom Comparator:

    Map <TimeZone, String> map = new TreeMap <TimeZone, String>();

    Which of course fails during runtime.

    --
    Wojtek :)
    Wojtek, Nov 3, 2009
    #14
  15. Wojtek

    Lew Guest

    Lew wrote :
    >>>   Map <TimeZone, String> map =
    >>>     new TreeMap <TimeZone, String> ( new Comparator <TimeZone> ()
    >>> { .... } );

    >


    Wojtek wrote:
    >> No arguments that this does work.

    >
    >> However I was replying to your statement "'TimeZone' can easily be a map
    >> key, yes, even for a 'TreeMap'. " which appears to say that you do not
    >> need a custom Comparator:

    >


    Even though I had explicitly mentioned a custom Comparator in the post
    to which you were replying? Come on, now. Your explanation is
    disingenuous at best.

    Patricia Shanahan wrote:
    > The natural order and comparator behaviors are equally valid. Throughout
    > the TreeMap documentation, unqualified statements apply to both cases.
    > Statements that only apply to the natural order case say so. Given the
    > way the TreeMap documentation is written, I would not assume a natural
    > order TreeMap is meant unless the writer says so.
    >


    In this case, the writer did explicitly mention use of a custom
    Comparator.

    > I think it is a mistake to treat a Comparable key type as the proper way
    > to use TreeMap or TreeSet, and a specified Comparator as somehow weird
    > or "indirect". It can create a mental block to what is often the best
    > choice for a sorted set or sorted map implementation, when either the
    > key type does not implement Comparable, or the required order is not its
    > Comparable order.
    >


    What she said, especially since I had actually referred to a custom
    Comparator in my post, and others had also chimed in with that same
    suggestion, including Wojtek himself! Pretending that that was not
    evident smacks of deliberate obtuseness.

    --
    Lew
    Lew, Nov 3, 2009
    #15
  16. Wojtek

    Wojtek Guest

    Lew wrote :
    > Lew wrote :
    >>>>   Map <TimeZone, String> map =
    >>>>     new TreeMap <TimeZone, String> ( new Comparator <TimeZone> ()
    >>>> { .... } );

    >>

    >
    > Wojtek wrote:
    >>> No arguments that this does work.

    >>
    >>> However I was replying to your statement "'TimeZone' can easily be a map
    >>> key, yes, even for a 'TreeMap'. " which appears to say that you do not
    >>> need a custom Comparator:

    >>

    >
    > Even though I had explicitly mentioned a custom Comparator in the post
    > to which you were replying? Come on, now. Your explanation is
    > disingenuous at best.


    To me a 'key' is the part which goes into the 'K' part of Map<K,V>.

    For a Comparator, the signature is Comparator<T> where the 'T' refers
    to a 'Type':
    http://www.j2ee.me/javase/6/docs/api/java/util/Comparator.html

    --
    Wojtek :)
    Wojtek, Nov 3, 2009
    #16
  17. Wojtek

    Wojtek Guest

    Eric Sosman wrote :
    > Wojtek wrote:
    >> Lew wrote :
    >>> Lew wrote :
    >>>>>> Map <TimeZone, String> map =
    >>>>>> new TreeMap <TimeZone, String> ( new Comparator <TimeZone> ()
    >>>>>> { .... } );
    >>>>
    >>>
    >>> Wojtek wrote:
    >>>>> No arguments that this does work.
    >>>>
    >>>>> However I was replying to your statement "'TimeZone' can easily be a map
    >>>>> key, yes, even for a 'TreeMap'. " which appears to say that you do not
    >>>>> need a custom Comparator:
    >>>>
    >>>
    >>> Even though I had explicitly mentioned a custom Comparator in the post
    >>> to which you were replying? Come on, now. Your explanation is
    >>> disingenuous at best.

    >>
    >> To me a 'key' is the part which goes into the 'K' part of Map<K,V>.

    >
    > Yes, that's right.
    >
    >> For a Comparator, the signature is Comparator<T> where the 'T' refers to a
    >> 'Type': http://www.j2ee.me/javase/6/docs/api/java/util/Comparator.html

    >
    > ... which means only that the K in Map<K,V> is the same as
    > the T in Comparator<T>, or is a subclass/subinterface of T. You
    > shouldn't read too much into the particular letters chosen to name
    > type parameters; the names are as arbitrary as those of method
    > parameters, and carry no deeper meaning.
    >
    > Does Map<String,String> bother you, because String == String
    > but K != V? If not, K != T shouldn't bother you, either, even if
    > you have a Map<Book,Date> and a Comparator<Book> with Book == Book.


    Semantics!

    We work in a precise field. An extra semi-colon can make a world of
    difference (brought down a phone system a few years ago).

    So yes, the labelling DOES make a difference. Whereas a Book is a Book,
    where it is used does change its meaning. So in Map<Book,Date>, Book is
    a key and in Comparator<Book>, Book is a Type.

    Otherwise the Javadoc author would not have made that distinction.

    It is used differently. As a key, it must provide its own comparison
    methodology. As a type, the Comparator makes the comparison, possibly
    using an external conversion such as I18N.

    --
    Wojtek :)
    Wojtek, Nov 3, 2009
    #17
  18. Wojtek

    Wojtek Guest

    Wojtek, Nov 4, 2009
    #18
  19. Wojtek

    Lew Guest

    Wojtek wrote:
    > Semantics!


    The word "semantics" means "meaning", so it isn't trivial.

    > We work in a precise field. An extra semi-colon can make a world of
    > difference (brought down a phone system a few years ago).
    >
    > So yes, the labelling DOES make a difference. Whereas a Book is a Book,
    > where it is used does change its meaning. So in Map<Book,Date>, Book is
    > a key and in Comparator<Book>, Book is a Type [sic].


    Now I see where your difficulty lies and I'm much more sympathetic to your cause.

    In both contexts the type parameter signifies a type. In 'Map <K, V>' there
    are two type parameters, indicating the types to which the Map is bound. The
    first is the type of the key, and the second is the type of the value.

    There is no semantic difference between expressing that as 'Map <K, V>',
    'Map <T, U>' or even 'Map <foo, bar>'.

    > Otherwise the Javadoc author would not have made that distinction.


    There is no distinction. The choice of letters in the Javadocs is arbitrary
    and designed to help us understand the usage of the two types managed by the
    'Map', but regardless a type parameter is a type parameter is a type parameter.

    > It is used differently. As a key, it must provide its own comparison
    > methodology. As a type, the Comparator makes the comparison, possibly
    > using an external conversion such as I18N.


    That is not true. Take a look again at the Javadocs for 'TreeMap' to which I
    pointed you earlier:

    <http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html#TreeMap(java.util.Comparator)>

    Note that they describe the comparator type parameter as '<? super K>' - that
    is the exact same 'K' as in the 'TreeMap <K, V>' type parameter.

    For further understanding, check out the rules for type parameters in the JLS.

    --
    Lew
    Lew, Nov 4, 2009
    #19
  20. Wojtek

    Lew Guest

    Wojtek wrote:
    >> It is used differently. As a key, it must provide its own comparison
    >> methodology. As a type, the Comparator makes the comparison, possibly
    >> using an external conversion such as I18N.


    Lew wrote:
    > That is not true. Take a look again at the Javadocs for 'TreeMap' to
    > which I pointed you earlier:
    >
    > <http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html#TreeMap(java.util.Comparator)>
    >
    > Note that they describe the comparator type parameter as '<? super K>' -
    > that is the exact same 'K' as in the 'TreeMap <K, V>' type parameter.


    I was unclear, in part because your antecedents are hazy. It is true that a
    'TreeMap' that uses "natural" order does not need a 'Comparator' and that one
    that needs a 'Comparator' does need a 'Comparator'. It is not true that the
    type parameter 'K' in 'TreeMap <K, V>' is different from the type parameter
    'K' in the 'TreeMap' constructor argument 'Comparator <? super K>'.

    --
    Lew
    Lew, Nov 4, 2009
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. asaf
    Replies:
    3
    Views:
    6,117
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=
    Sep 11, 2006
  2. axrock
    Replies:
    8
    Views:
    928
    Roedy Green
    Mar 25, 2009
  3. Replies:
    2
    Views:
    1,392
    James Kanze
    Jul 6, 2010
  4. Jason
    Replies:
    0
    Views:
    363
    Jason
    Oct 4, 2006
  5. Ami
    Replies:
    5
    Views:
    259
Loading...

Share This Page