001    /*
002     * Copyleft notice: This is public-domain software and documentation
003     * with no restrictions of any kind.
004     * Please feel free to use any of it in any way you want.
005     * This work is distributed in the hope that it will be useful,
006     * but WITHOUT ANY WARRANTY; without even the implied warranty of
007     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
008     */
009    
010    
011    package time;
012    
013    import java.util.*;
014    
015    /**
016     * Definition a day of the week.
017     *
018     * <p>Unlike month, this class is not an <tt>Enum</tt>, because <tt>DayOfWeek</tt> does not
019     * have a <i>natural order</i>. More precisely, even if everyone agrees on the
020     * order of weekdays, the first day of the week depends on the local usage.
021     *
022     * <p>This class provides also static method to have several appropriate
023     * <tt>Comparator</tt> or <tt>SortedSet</tt> where the first conventionnal day of the
024     * week has been set.
025     * 
026     *
027     * @author Arnaud Roques
028     */
029    public final class DayOfWeek
030    {
031            private final static WeekDayComparator[] COMPARATOR;
032            private final static SortedSet<DayOfWeek>[] SORTED_SET;
033            private final static Map<String, DayOfWeek> valueOfMap = new HashMap<String, DayOfWeek>(7);
034    
035            public static final DayOfWeek SUNDAY = new DayOfWeek(GregorianCalendar.SUNDAY, "SUNDAY");
036            public static final DayOfWeek MONDAY = new DayOfWeek(GregorianCalendar.MONDAY, "MONDAY");
037            public static final DayOfWeek TUESDAY = new DayOfWeek(GregorianCalendar.TUESDAY, "TUESDAY");
038            public static final DayOfWeek WEDNESDAY = new DayOfWeek(GregorianCalendar.WEDNESDAY, "WEDNESDAY");
039            public static final DayOfWeek THURSDAY = new DayOfWeek(GregorianCalendar.THURSDAY, "THURSDAY");
040            public static final DayOfWeek FRIDAY = new DayOfWeek(GregorianCalendar.FRIDAY, "FRIDAY");
041            public static final DayOfWeek SATURDAY = new DayOfWeek(GregorianCalendar.SATURDAY, "SATURDAY");
042            
043            private final int gcValue;
044            private final String name;
045            
046            static class WeekDayComparator implements Comparator<DayOfWeek>
047            {
048                    private final int modulo;
049                    
050                    WeekDayComparator(int modulo)
051                    {
052                            this.modulo = modulo;
053                    }
054                    
055                    public int compare(DayOfWeek d1, DayOfWeek d2)
056                    {
057                            return modulo(d1.gcValue) - modulo(d2.gcValue);
058                    }
059                    
060                    private int modulo(int i)
061                    {
062                            return (i-1-modulo+7)%7;
063                    }
064            }
065            
066            
067            static
068            {
069                    COMPARATOR = new WeekDayComparator[7];
070                    for (int i=0; i<COMPARATOR.length; i++) COMPARATOR[i] = new WeekDayComparator(i);
071                    SORTED_SET = new SortedSet[7];
072                    List<DayOfWeek> all = Arrays.asList(SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
073                                            THURSDAY, FRIDAY, SATURDAY);
074                    for (int i=0; i<SORTED_SET.length; i++)
075                    {
076                            SORTED_SET[i] = new TreeSet<DayOfWeek>(COMPARATOR[i]);
077                            SORTED_SET[i].addAll(all);
078                            SORTED_SET[i] = Collections.unmodifiableSortedSet(SORTED_SET[i]);
079                    }
080            }
081            
082            /**
083             * Return a <tt>Comparator</tt> for sorting <tt>DayOfWeek</tt>.
084             *
085             * <p>
086             * The conventionnal first week of the day must be provided,
087             * so that the <tt>Comparator</tt>
088             * can do his job.
089             *
090             * @param firstWeekDay  conventionnal first day of week
091             *
092             * @return a <tt>Comparator</tt> that compare <tt>DayOfWeek</tt> objects
093             *              using a precise first day of week
094             */
095            static public Comparator<DayOfWeek> specialComparator(DayOfWeek firstWeekDay)
096            {
097                    return COMPARATOR[firstWeekDay.gcValue-1];
098            }
099    
100            /**
101             * Return a immutable <tt>SortedSet</tt> with all seven <tt>DayOfWeek</tt>.
102             *
103             * <p>
104             * The conventionnal first week of the day must be provided.
105             *
106             * @param firstWeekDay  conventionnal first day of week
107             *
108             * @return a <tt>SortedSet</tt> with all seven <tt>DayOfWeek</tt>, starting with
109             *              <tt>firstWeekDay</tt>
110             */
111            static public SortedSet<DayOfWeek> specialSet(DayOfWeek firstWeekDay)
112            {
113                    return SORTED_SET[firstWeekDay.gcValue-1];
114            }
115            
116            private DayOfWeek(int gcValue, String name)
117            {
118                    this.gcValue = gcValue;
119                    this.name = name;
120                    valueOfMap.put(name, this);
121            }
122            
123            /**
124             * Return the <tt>java.util.Calendar</tt> integer constant corresponding to
125             * this <tt>DayWeek</tt> object.
126             *
127             * <p>
128             * This method should be use only for compatibility with <tt>java.util.Calendar</tt>.
129             *
130             * @return the <tt>java.util.Calendar</tt> integer constant corresponding to
131             * this <tt>DayWeek</tt> object.
132             */
133            public int getGcValue()
134            {
135                    return gcValue;
136            }
137            
138            /**
139             * Return a <tt>String</tt> describing the <tt>DayOfWeek</tt>
140             *
141             * @return a <tt>String</tt> describing the <tt>DayOfWeek</tt>
142             * @hidden
143             */
144            @Override
145            public String toString()
146            {
147                    return name;
148            }
149            
150            /**
151             * Returns the <tt>DayOfWeek</tt> object with the specified name.
152             *
153             * @param name  the name of the weekday to be returned
154             *
155             * @return the <tt>DayOfWeek</tt> object with the specified name.
156             *
157             * @throws IllegalArgumentException     if <tt>name</tt> is not a valid weekday name.
158             */
159            public static DayOfWeek valueOf(String name)
160            {
161                    DayOfWeek result = valueOfMap.get(name);
162                    if (result==null) throw new IllegalArgumentException();
163                    return result;
164            }
165    
166    
167            /**
168             * Returns the <tt>DayOfWeek</tt> object with the specified <tt>java.util.Calendar</tt>
169             * integer constant.
170             *
171             * @param gc    a integer from <tt>java.util.Calendar</tt> weekday constants.
172             *
173             * @return the <tt>DayOfWeek</tt> object with the specified <tt>java.util.Calendar</tt>
174             * integer constant.
175             *
176             * @throws IllegalArgumentException     if <tt>gc</tt> is not a valid integer constant.
177             */
178            public static DayOfWeek fromGcValue(int gc)
179            {
180                    for (DayOfWeek d : valueOfMap.values())
181                            if (d.gcValue==gc) return d;
182                    throw new IllegalArgumentException();
183            }
184            
185            /*
186            public static void main(String arg[])
187            {
188                    System.err.println(specialSet(DayOfWeek.SUNDAY));
189                    System.err.println(specialSet(DayOfWeek.MONDAY));
190                    System.err.println(specialSet(DayOfWeek.TUESDAY));
191                    System.err.println(specialSet(DayOfWeek.WEDNESDAY));
192                    System.err.println(specialSet(DayOfWeek.THURSDAY));
193                    System.err.println(specialSet(DayOfWeek.FRIDAY));
194                    System.err.println(specialSet(DayOfWeek.SATURDAY));
195            }*/
196            
197    }
198