1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.util;
19
20import java.io.IOException;
21import java.io.ObjectInputStream;
22import java.io.ObjectOutputStream;
23import java.io.Serializable;
24import java.text.DateFormat;
25import java.text.DateFormatSymbols;
26import java.text.SimpleDateFormat;
27
28import org.apache.harmony.luni.internal.nls.Messages;
29
30/**
31 * {@code Date} represents a specific moment in time, to the millisecond.
32 *
33 * @see System#currentTimeMillis
34 * @see Calendar
35 * @see GregorianCalendar
36 * @see SimpleTimeZone
37 * @see TimeZone
38 * @since Android 1.0
39 */
40public class Date implements Serializable, Cloneable, Comparable<Date> {
41
42    private static final long serialVersionUID = 7523967970034938905L;
43
44    // Used by parse()
45    private static int creationYear = new Date().getYear();
46
47    private transient long milliseconds;
48
49    /**
50     * Initializes this {@code Date} instance to the current date and time.
51     *
52     * @since Android 1.0
53     */
54    public Date() {
55        this(System.currentTimeMillis());
56    }
57
58    /**
59     * Constructs a new {@code Date} initialized to midnight in the default {@code TimeZone} on
60     * the specified date.
61     *
62     * @param year
63     *            the year, 0 is 1900.
64     * @param month
65     *            the month, 0 - 11.
66     * @param day
67     *            the day of the month, 1 - 31.
68     *
69     * @deprecated use
70     *             {@link GregorianCalendar#GregorianCalendar(int, int, int)}
71     * @since Android 1.0
72     */
73    @Deprecated
74    public Date(int year, int month, int day) {
75        GregorianCalendar cal = new GregorianCalendar(false);
76        cal.set(1900 + year, month, day);
77        milliseconds = cal.getTimeInMillis();
78    }
79
80    /**
81     * Constructs a new {@code Date} initialized to the specified date and time in the
82     * default {@code TimeZone}.
83     *
84     * @param year
85     *            the year, 0 is 1900.
86     * @param month
87     *            the month, 0 - 11.
88     * @param day
89     *            the day of the month, 1 - 31.
90     * @param hour
91     *            the hour of day, 0 - 23.
92     * @param minute
93     *            the minute of the hour, 0 - 59.
94     *
95     * @deprecated use
96     *             {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int)}
97     * @since Android 1.0
98     */
99    @Deprecated
100    public Date(int year, int month, int day, int hour, int minute) {
101        GregorianCalendar cal = new GregorianCalendar(false);
102        cal.set(1900 + year, month, day, hour, minute);
103        milliseconds = cal.getTimeInMillis();
104    }
105
106    /**
107     * Constructs a new {@code Date} initialized to the specified date and time in the
108     * default {@code TimeZone}.
109     *
110     * @param year
111     *            the year, 0 is 1900.
112     * @param month
113     *            the month, 0 - 11.
114     * @param day
115     *            the day of the month, 1 - 31.
116     * @param hour
117     *            the hour of day, 0 - 23.
118     * @param minute
119     *            the minute of the hour, 0 - 59.
120     * @param second
121     *            the second of the minute, 0 - 59.
122     *
123     * @deprecated use
124     *             {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int, int)}
125     * @since Android 1.0
126     */
127    @Deprecated
128    public Date(int year, int month, int day, int hour, int minute, int second) {
129        GregorianCalendar cal = new GregorianCalendar(false);
130        cal.set(1900 + year, month, day, hour, minute, second);
131        milliseconds = cal.getTimeInMillis();
132    }
133
134    /**
135     * Initializes this {@code Date} instance using the specified millisecond value. The
136     * value is the number of milliseconds since Jan. 1, 1970 GMT.
137     *
138     * @param milliseconds
139     *            the number of milliseconds since Jan. 1, 1970 GMT.
140     * @since Android 1.0
141     */
142    public Date(long milliseconds) {
143        this.setTime(milliseconds);
144    }
145
146    /**
147     * Constructs a new {@code Date} initialized to the date and time parsed from the
148     * specified String.
149     *
150     * @param string
151     *            the String to parse.
152     *
153     * @deprecated use {@link DateFormat}
154     * @since Android 1.0
155     */
156    @Deprecated
157    public Date(String string) {
158        milliseconds = parse(string);
159    }
160
161    /**
162     * Returns if this {@code Date} is after the specified Date.
163     *
164     * @param date
165     *            a Date instance to compare.
166     * @return {@code true} if this {@code Date} is after the specified {@code Date},
167     *         {@code false} otherwise.
168     * @since Android 1.0
169     */
170    public boolean after(Date date) {
171        return milliseconds > date.milliseconds;
172    }
173
174    /**
175     * Returns if this {@code Date} is before the specified Date.
176     *
177     * @param date
178     *            a {@code Date} instance to compare.
179     * @return {@code true} if this {@code Date} is before the specified {@code Date},
180     *         {@code false} otherwise.
181     * @since Android 1.0
182     */
183    public boolean before(Date date) {
184        return milliseconds < date.milliseconds;
185    }
186
187    /**
188     * Returns a new {@code Date} with the same millisecond value as this {@code Date}.
189     *
190     * @return a shallow copy of this {@code Date}.
191     *
192     * @see java.lang.Cloneable
193     * @since Android 1.0
194     */
195    @Override
196    public Object clone() {
197        try {
198            return super.clone();
199        } catch (CloneNotSupportedException e) {
200            return null;
201        }
202    }
203
204    /**
205     * Compare the receiver to the specified {@code Date} to determine the relative
206     * ordering.
207     *
208     * @param date
209     *            a {@code Date} to compare against.
210     * @return an {@code int < 0} if this {@code Date} is less than the specified {@code Date}, {@code 0} if
211     *         they are equal, and an {@code int > 0} if this {@code Date} is greater.
212     * @since Android 1.0
213     */
214    public int compareTo(Date date) {
215        if (milliseconds < date.milliseconds) {
216            return -1;
217        }
218        if (milliseconds == date.milliseconds) {
219            return 0;
220        }
221        return 1;
222    }
223
224    /**
225     * Compares the specified object to this {@code Date} and returns if they are equal.
226     * To be equal, the object must be an instance of {@code Date} and have the same millisecond
227     * value.
228     *
229     * @param object
230     *            the object to compare with this object.
231     * @return {@code true} if the specified object is equal to this {@code Date}, {@code false}
232     *         otherwise.
233     *
234     * @see #hashCode
235     * @since Android 1.0
236     */
237    @Override
238    public boolean equals(Object object) {
239        return (object == this) || (object instanceof Date)
240                && (milliseconds == ((Date) object).milliseconds);
241    }
242
243    /**
244     * Returns the gregorian calendar day of the month for this {@code Date} object.
245     *
246     * @return the day of the month.
247     *
248     * @deprecated use {@code Calendar.get(Calendar.DATE)}
249     * @since Android 1.0
250     */
251    @Deprecated
252    public int getDate() {
253        return new GregorianCalendar(milliseconds).get(Calendar.DATE);
254    }
255
256    /**
257     * Returns the gregorian calendar day of the week for this {@code Date} object.
258     *
259     * @return the day of the week.
260     *
261     * @deprecated use {@code Calendar.get(Calendar.DAY_OF_WEEK)}
262     * @since Android 1.0
263     */
264    @Deprecated
265    public int getDay() {
266        return new GregorianCalendar(milliseconds).get(Calendar.DAY_OF_WEEK) - 1;
267    }
268
269    /**
270     * Returns the gregorian calendar hour of the day for this {@code Date} object.
271     *
272     * @return the hour of the day.
273     *
274     * @deprecated use {@code Calendar.get(Calendar.HOUR_OF_DAY)}
275     * @since Android 1.0
276     */
277    @Deprecated
278    public int getHours() {
279        return new GregorianCalendar(milliseconds).get(Calendar.HOUR_OF_DAY);
280    }
281
282    /**
283     * Returns the gregorian calendar minute of the hour for this {@code Date} object.
284     *
285     * @return the minutes.
286     *
287     * @deprecated use {@code Calendar.get(Calendar.MINUTE)}
288     * @since Android 1.0
289     */
290    @Deprecated
291    public int getMinutes() {
292        return new GregorianCalendar(milliseconds).get(Calendar.MINUTE);
293    }
294
295    /**
296     * Returns the gregorian calendar month for this {@code Date} object.
297     *
298     * @return the month.
299     *
300     * @deprecated use {@code Calendar.get(Calendar.MONTH)}
301     * @since Android 1.0
302     */
303    @Deprecated
304    public int getMonth() {
305        return new GregorianCalendar(milliseconds).get(Calendar.MONTH);
306    }
307
308    /**
309     * Returns the gregorian calendar second of the minute for this {@code Date} object.
310     *
311     * @return the seconds.
312     *
313     * @deprecated use {@code Calendar.get(Calendar.SECOND)}
314     * @since Android 1.0
315     */
316    @Deprecated
317    public int getSeconds() {
318        return new GregorianCalendar(milliseconds).get(Calendar.SECOND);
319    }
320
321    /**
322     * Returns this {@code Date} as a millisecond value. The value is the number of
323     * milliseconds since Jan. 1, 1970, midnight GMT.
324     *
325     * @return the number of milliseconds since Jan. 1, 1970, midnight GMT.
326     * @since Android 1.0
327     */
328    public long getTime() {
329        return milliseconds;
330    }
331
332    /**
333     * Returns the timezone offset in minutes of the default {@code TimeZone}.
334     *
335     * @return the timezone offset in minutes of the default {@code TimeZone}.
336     *
337     * @deprecated use
338     *             {@code (Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / 60000}
339     * @since Android 1.0
340     */
341    @Deprecated
342    public int getTimezoneOffset() {
343        GregorianCalendar cal = new GregorianCalendar(milliseconds);
344        return -(cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / 60000;
345    }
346
347    /**
348     * Returns the gregorian calendar year since 1900 for this {@code Date} object.
349     *
350     * @return the year - 1900.
351     *
352     * @deprecated use {@code Calendar.get(Calendar.YEAR) - 1900}
353     * @since Android 1.0
354     */
355    @Deprecated
356    public int getYear() {
357        return new GregorianCalendar(milliseconds).get(Calendar.YEAR) - 1900;
358    }
359
360    /**
361     * Returns an integer hash code for the receiver. Objects which are equal
362     * return the same value for this method.
363     *
364     * @return this {@code Date}'s hash.
365     *
366     * @see #equals
367     * @since Android 1.0
368     */
369    @Override
370    public int hashCode() {
371        return (int) (milliseconds >>> 32) ^ (int) milliseconds;
372    }
373
374    private static int parse(String string, String[] array) {
375        for (int i = 0, alength = array.length, slength = string.length(); i < alength; i++) {
376            if (string.regionMatches(true, 0, array[i], 0, slength)) {
377                return i;
378            }
379        }
380        return -1;
381    }
382
383    /**
384     * Returns the millisecond value of the date and time parsed from the
385     * specified {@code String}. Many date/time formats are recognized, including IETF
386     * standard syntax, i.e. Tue, 22 Jun 1999 12:16:00 GMT-0500
387     *
388     * @param string
389     *            the String to parse.
390     * @return the millisecond value parsed from the String.
391     *
392     * @deprecated use {@link DateFormat}
393     * @since Android 1.0
394     */
395    @Deprecated
396    public static long parse(String string) {
397
398        if (string == null) {
399            // luni.06=The string argument is null
400            throw new IllegalArgumentException(Messages.getString("luni.06")); //$NON-NLS-1$
401        }
402
403        char sign = 0;
404        int commentLevel = 0;
405        int offset = 0, length = string.length(), state = 0;
406        int year = -1, month = -1, date = -1;
407        int hour = -1, minute = -1, second = -1, zoneOffset = 0;
408        boolean zone = false;
409        final int PAD = 0, LETTERS = 1, NUMBERS = 2;
410        StringBuffer buffer = new StringBuffer();
411
412        while (offset <= length) {
413            char next = offset < length ? string.charAt(offset) : '\r';
414            offset++;
415
416            if (next == '(') {
417                commentLevel++;
418            }
419            if (commentLevel > 0) {
420                if (next == ')') {
421                    commentLevel--;
422                }
423                if (commentLevel == 0) {
424                    next = ' ';
425                } else {
426                    continue;
427                }
428            }
429
430            int nextState = PAD;
431            if ('a' <= next && next <= 'z' || 'A' <= next && next <= 'Z') {
432                nextState = LETTERS;
433            } else if ('0' <= next && next <= '9') {
434                nextState = NUMBERS;
435            } else if (!Character.isSpace(next) && ",+-:/".indexOf(next) == -1) { //$NON-NLS-1$
436                throw new IllegalArgumentException();
437            }
438
439            if (state == NUMBERS && nextState != NUMBERS) {
440                int digit = Integer.parseInt(buffer.toString());
441                buffer.setLength(0);
442                if (sign == '+' || sign == '-') {
443                    if (zoneOffset == 0) {
444                        zone = true;
445                        zoneOffset = sign == '-' ? -digit : digit;
446                        sign = 0;
447                    } else {
448                        throw new IllegalArgumentException();
449                    }
450                } else if (digit >= 70) {
451                    if (year == -1
452                            && (Character.isSpace(next) || next == ','
453                                    || next == '/' || next == '\r')) {
454                        year = digit;
455                    } else {
456                        throw new IllegalArgumentException();
457                    }
458                } else if (next == ':') {
459                    if (hour == -1) {
460                        hour = digit;
461                    } else if (minute == -1) {
462                        minute = digit;
463                    } else {
464                        throw new IllegalArgumentException();
465                    }
466                } else if (next == '/') {
467                    if (month == -1) {
468                        month = digit - 1;
469                    } else if (date == -1) {
470                        date = digit;
471                    } else {
472                        throw new IllegalArgumentException();
473                    }
474                } else if (Character.isSpace(next) || next == ','
475                        || next == '-' || next == '\r') {
476                    if (hour != -1 && minute == -1) {
477                        minute = digit;
478                    } else if (minute != -1 && second == -1) {
479                        second = digit;
480                    } else if (date == -1) {
481                        date = digit;
482                    } else if (year == -1) {
483                        year = digit;
484                    } else {
485                        throw new IllegalArgumentException();
486                    }
487                } else if (year == -1 && month != -1 && date != -1) {
488                    year = digit;
489                } else {
490                    throw new IllegalArgumentException();
491                }
492            } else if (state == LETTERS && nextState != LETTERS) {
493                String text = buffer.toString().toUpperCase();
494                buffer.setLength(0);
495                if (text.length() == 1) {
496                    throw new IllegalArgumentException();
497                }
498                if (text.equals("AM")) { //$NON-NLS-1$
499                    if (hour == 12) {
500                        hour = 0;
501                    } else if (hour < 1 || hour > 12) {
502                        throw new IllegalArgumentException();
503                    }
504                } else if (text.equals("PM")) { //$NON-NLS-1$
505                    if (hour == 12) {
506                        hour = 0;
507                    } else if (hour < 1 || hour > 12) {
508                        throw new IllegalArgumentException();
509                    }
510                    hour += 12;
511                } else {
512                    DateFormatSymbols symbols = new DateFormatSymbols(Locale.US);
513                    String[] weekdays = symbols.getWeekdays(), months = symbols
514                            .getMonths();
515                    int value;
516                    if (parse(text, weekdays) != -1) {/* empty */
517                    } else if (month == -1
518                            && (month = parse(text, months)) != -1) {/* empty */
519                    } else if (text.equals("GMT") || text.equals("UT") //$NON-NLS-1$ //$NON-NLS-2$
520                            || text.equals("UTC")) { //$NON-NLS-1$
521                        zone = true;
522                        zoneOffset = 0;
523                    } else if ((value = zone(text)) != 0) {
524                        zone = true;
525                        zoneOffset = value;
526                    } else {
527                        throw new IllegalArgumentException();
528                    }
529                }
530            }
531
532            if (next == '+' || (year != -1 && next == '-')) {
533                sign = next;
534            } else if (!Character.isSpace(next) && next != ','
535                    && nextState != NUMBERS) {
536                sign = 0;
537            }
538
539            if (nextState == LETTERS || nextState == NUMBERS) {
540                buffer.append(next);
541            }
542            state = nextState;
543        }
544
545        if (year != -1 && month != -1 && date != -1) {
546            if (hour == -1) {
547                hour = 0;
548            }
549            if (minute == -1) {
550                minute = 0;
551            }
552            if (second == -1) {
553                second = 0;
554            }
555            if (year < (creationYear - 80)) {
556                year += 2000;
557            } else if (year < 100) {
558                year += 1900;
559            }
560            if (zone) {
561                if (zoneOffset >= 24 || zoneOffset <= -24) {
562                    hour -= zoneOffset / 100;
563                    minute -= zoneOffset % 100;
564                } else {
565                    hour -= zoneOffset;
566                }
567                return UTC(year - 1900, month, date, hour, minute, second);
568            }
569            return new Date(year - 1900, month, date, hour, minute, second)
570                    .getTime();
571        }
572        throw new IllegalArgumentException();
573    }
574
575    /**
576     * Sets the gregorian calendar day of the month for this {@code Date} object.
577     *
578     * @param day
579     *            the day of the month.
580     *
581     * @deprecated use {@code Calendar.set(Calendar.DATE, day)}
582     * @since Android 1.0
583     */
584    @Deprecated
585    public void setDate(int day) {
586        GregorianCalendar cal = new GregorianCalendar(milliseconds);
587        cal.set(Calendar.DATE, day);
588        milliseconds = cal.getTimeInMillis();
589    }
590
591    /**
592     * Sets the gregorian calendar hour of the day for this {@code Date} object.
593     *
594     * @param hour
595     *            the hour of the day.
596     *
597     * @deprecated use {@code Calendar.set(Calendar.HOUR_OF_DAY, hour)}
598     * @since Android 1.0
599     */
600    @Deprecated
601    public void setHours(int hour) {
602        GregorianCalendar cal = new GregorianCalendar(milliseconds);
603        cal.set(Calendar.HOUR_OF_DAY, hour);
604        milliseconds = cal.getTimeInMillis();
605    }
606
607    /**
608     * Sets the gregorian calendar minute of the hour for this {@code Date} object.
609     *
610     * @param minute
611     *            the minutes.
612     *
613     * @deprecated use {@code Calendar.set(Calendar.MINUTE, minute)}
614     * @since Android 1.0
615     */
616    @Deprecated
617    public void setMinutes(int minute) {
618        GregorianCalendar cal = new GregorianCalendar(milliseconds);
619        cal.set(Calendar.MINUTE, minute);
620        milliseconds = cal.getTimeInMillis();
621    }
622
623    /**
624     * Sets the gregorian calendar month for this {@code Date} object.
625     *
626     * @param month
627     *            the month.
628     *
629     * @deprecated use {@code Calendar.set(Calendar.MONTH, month)}
630     * @since Android 1.0
631     */
632    @Deprecated
633    public void setMonth(int month) {
634        GregorianCalendar cal = new GregorianCalendar(milliseconds);
635        cal.set(Calendar.MONTH, month);
636        milliseconds = cal.getTimeInMillis();
637    }
638
639    /**
640     * Sets the gregorian calendar second of the minute for this {@code Date} object.
641     *
642     * @param second
643     *            the seconds.
644     *
645     * @deprecated use {@code Calendar.set(Calendar.SECOND, second)}
646     * @since Android 1.0
647     */
648    @Deprecated
649    public void setSeconds(int second) {
650        GregorianCalendar cal = new GregorianCalendar(milliseconds);
651        cal.set(Calendar.SECOND, second);
652        milliseconds = cal.getTimeInMillis();
653    }
654
655    /**
656     * Sets this {@code Date} to the specified millisecond value. The value is the
657     * number of milliseconds since Jan. 1, 1970 GMT.
658     *
659     * @param milliseconds
660     *            the number of milliseconds since Jan. 1, 1970 GMT.
661     * @since Android 1.0
662     */
663    public void setTime(long milliseconds) {
664        this.milliseconds = milliseconds;
665    }
666
667    /**
668     * Sets the gregorian calendar year since 1900 for this {@code Date} object.
669     *
670     * @param year
671     *            the year since 1900.
672     *
673     * @deprecated use {@code Calendar.set(Calendar.YEAR, year + 1900)}
674     * @since Android 1.0
675     */
676    @Deprecated
677    public void setYear(int year) {
678        GregorianCalendar cal = new GregorianCalendar(milliseconds);
679        cal.set(Calendar.YEAR, year + 1900);
680        milliseconds = cal.getTimeInMillis();
681    }
682
683    /**
684     * Returns the string representation of this {@code Date} in GMT in the format: 22
685     * Jun 1999 13:02:00 GMT
686     *
687     * @return the string representation of this {@code Date} in GMT.
688     *
689     * @deprecated use {@link DateFormat}
690     * @since Android 1.0
691     */
692    @Deprecated
693    public String toGMTString() {
694        SimpleDateFormat format1 = new SimpleDateFormat("d MMM ", Locale.US); //$NON-NLS-1$
695        SimpleDateFormat format2 = new SimpleDateFormat(
696                " HH:mm:ss 'GMT'", Locale.US); //$NON-NLS-1$
697        TimeZone gmtZone = TimeZone.getTimeZone("GMT"); //$NON-NLS-1$
698        format1.setTimeZone(gmtZone);
699        format2.setTimeZone(gmtZone);
700        GregorianCalendar gc = new GregorianCalendar(gmtZone);
701        gc.setTimeInMillis(milliseconds);
702        return format1.format(this) + gc.get(Calendar.YEAR)
703                + format2.format(this);
704    }
705
706    /**
707     * Returns the string representation of this {@code Date} for the default {@code Locale}.
708     *
709     * @return the string representation of this {@code Date} for the default {@code Locale}.
710     *
711     * @deprecated use {@link DateFormat}
712     * @since Android 1.0
713     */
714    @Deprecated
715    public String toLocaleString() {
716        return DateFormat.getDateTimeInstance().format(this);
717    }
718
719    /**
720     * Returns the string representation of this {@code Date} in the format: Tue Jun 22
721     * 13:07:00 GMT 1999
722     *
723     * @return the string representation of this {@code Date}.
724     * @since Android 1.0
725     */
726    @Override
727    public String toString() {
728        return new SimpleDateFormat("E MMM dd HH:mm:ss z ", Locale.US) //$NON-NLS-1$
729                .format(this)
730                + new GregorianCalendar(milliseconds).get(Calendar.YEAR);
731    }
732
733    /**
734     * Returns the millisecond value of the specified date and time in GMT.
735     *
736     * @param year
737     *            the year, 0 is 1900.
738     * @param month
739     *            the month, 0 - 11.
740     * @param day
741     *            the day of the month, 1 - 31.
742     * @param hour
743     *            the hour of day, 0 - 23.
744     * @param minute
745     *            the minute of the hour, 0 - 59.
746     * @param second
747     *            the second of the minute, 0 - 59.
748     * @return the date and time in GMT in milliseconds.
749     *
750     * @deprecated use: <code>
751     *  Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
752     *  cal.set(year + 1900, month, day, hour, minute, second);
753     *  cal.getTime().getTime();</code>
754     * @since Android 1.0
755     */
756    @Deprecated
757    public static long UTC(int year, int month, int day, int hour, int minute,
758            int second) {
759        GregorianCalendar cal = new GregorianCalendar(false);
760        cal.setTimeZone(TimeZone.getTimeZone("GMT")); //$NON-NLS-1$
761        cal.set(1900 + year, month, day, hour, minute, second);
762        return cal.getTimeInMillis();
763    }
764
765    private static int zone(String text) {
766        if (text.equals("EST")) { //$NON-NLS-1$
767            return -5;
768        }
769        if (text.equals("EDT")) { //$NON-NLS-1$
770            return -4;
771        }
772        if (text.equals("CST")) { //$NON-NLS-1$
773            return -6;
774        }
775        if (text.equals("CDT")) { //$NON-NLS-1$
776            return -5;
777        }
778        if (text.equals("MST")) { //$NON-NLS-1$
779            return -7;
780        }
781        if (text.equals("MDT")) { //$NON-NLS-1$
782            return -6;
783        }
784        if (text.equals("PST")) { //$NON-NLS-1$
785            return -8;
786        }
787        if (text.equals("PDT")) { //$NON-NLS-1$
788            return -7;
789        }
790        return 0;
791    }
792
793    private void writeObject(ObjectOutputStream stream) throws IOException {
794        stream.defaultWriteObject();
795        stream.writeLong(getTime());
796    }
797
798    private void readObject(ObjectInputStream stream) throws IOException,
799            ClassNotFoundException {
800        stream.defaultReadObject();
801        setTime(stream.readLong());
802    }
803}
804