KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > lib > DateModule


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.quercus.lib;
31
32 import com.caucho.quercus.annotation.Optional;
33 import com.caucho.quercus.env.*;
34 import com.caucho.quercus.module.AbstractQuercusModule;
35 import com.caucho.util.Alarm;
36 import com.caucho.util.CharBuffer;
37 import com.caucho.util.L10N;
38 import com.caucho.util.QDate;
39
40 import java.util.TimeZone JavaDoc;
41 import java.util.logging.Level JavaDoc;
42 import java.util.logging.Logger JavaDoc;
43
44 /**
45  * Date functions.
46  */

47 public class DateModule extends AbstractQuercusModule {
48   private static final L10N L = new L10N(DateModule.class);
49   private static final Logger JavaDoc log
50     = Logger.getLogger(DateModule.class.getName());
51
52   public static final int CAL_GREGORIAN = 0;
53   public static final int CAL_JULIAN = 1;
54
55   private static final String JavaDoc []_shortDayOfWeek = {
56     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
57   };
58
59   private static final String JavaDoc []_fullDayOfWeek = {
60     "Sunday", "Monday", "Tuesday", "Wednesday",
61     "Thursday", "Friday", "Saturday", "Sunday"
62   };
63
64   private static final String JavaDoc []_shortMonth = {
65     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
66     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
67   };
68   private static final String JavaDoc []_fullMonth = {
69     "January", "February", "March", "April", "May", "June",
70     "July", "August", "September", "October", "November", "December",
71   };
72
73   private static final long MINUTE = 60000L;
74   private static final long HOUR = 60 * MINUTE;
75   private static final long DAY = 24 * HOUR;
76
77   private QDate _localCalendar = QDate.createLocal();
78   private QDate _gmtCalendar = new QDate();
79
80   /**
81    * Returns the days in a given month.
82    */

83   public static int cal_days_in_month(int cal, int month, int year)
84   {
85     QDate date = new QDate();
86
87     date.setYear(year);
88     date.setMonth(month - 1);
89
90     return date.getDaysInMonth();
91   }
92
93   /**
94    * Returns the days in a given month.
95    */

96   public static boolean checkdate(int month, int day, int year)
97   {
98     if (! (1 <= year && year <= 32767))
99       return false;
100     
101     if (! (1 <= month && month <= 12))
102       return false;
103
104     return 1 <= day && day <= cal_days_in_month(0, month, year);
105   }
106
107
108   /**
109    * Returns the formatted date.
110    */

111   public String JavaDoc date(String JavaDoc format,
112              @Optional("time()") long time)
113   {
114     return date(format, time, false);
115   }
116
117   /**
118    * Returns the timestamp of easter.
119    */

120   public static long easter_date(@Optional("-1") int year)
121   {
122     QDate date = new QDate();
123     
124     if (year < 0) {
125       date.setGMTTime(Alarm.getCurrentTime());
126       
127       year = date.getYear();
128     }
129
130     int y = year;
131
132     int c = y / 100;
133     int n = y - 19 * (y / 19);
134     int k = (c - 17) / 25;
135     int i = c - c /4 - (c - k) / 3 + 19 * n + 15;
136     i = i - 30 * (i / 30);
137     i = i - (i / 28) * (1 - ((i / 28) *
138                  (29 / (i + 1)) *
139                  ((21 - n) / 11)));
140
141     int j = y + y / 4 + i + 2 - c + c / 4;
142     j = j - 7 * (j / 7);
143     int l = i - j;
144     int m = 3 + (l + 40) / 44;
145     int d = l + 28 - 31 * (m / 4);
146
147     date.setYear(year);
148     date.setMonth(m - 1);
149     date.setDayOfMonth(d);
150
151     return date.getGMTTime() / 1000;
152   }
153
154   /**
155    * Returns the timestamp of easter.
156    */

157   public static long easter_days(@Optional("-1") int year,
158                  @Optional int method)
159   {
160     return easter_date(year);
161   }
162
163   /**
164    * Returns an array of the current date.
165    */

166   public Value getdate(@Optional("time()") long time)
167   {
168     QDate date = new QDate(false);
169
170     date.setLocalTime(1000 * time);
171
172     ArrayValue array = new ArrayValueImpl();
173
174     array.put("seconds", date.getSecond());
175     array.put("minutes", date.getMinute());
176     array.put("hours", date.getHour());
177     array.put("mday", date.getDayOfMonth());
178     array.put("wday", date.getDayOfWeek());
179     array.put("mon", date.getMonth() + 1);
180     array.put("year", date.getYear());
181     array.put("yday", date.getDayOfYear());
182     array.put("weekday", _fullDayOfWeek[date.getDayOfWeek()]);
183     array.put("month", _fullMonth[date.getMonth()]);
184     array.put(new LongValue(0), new LongValue(time));
185
186     return array;
187   }
188
189   public Value gettimeofday(@Optional boolean isFloatReturn)
190   {
191     long gmtTime = Alarm.getCurrentTime();
192
193     if (isFloatReturn) {
194       return new DoubleValue(((double) Alarm.getCurrentTime()) / 1000.0);
195     }
196     else {
197       ArrayValueImpl result = new ArrayValueImpl();
198
199       TimeZone JavaDoc localTimeZone = TimeZone.getDefault();
200
201       long sec = gmtTime / 1000L;
202       long microsec = (gmtTime - (sec * 1000)) * 1000L;
203       long minutesWest = localTimeZone.getRawOffset() / 1000L / 60L * -1L;
204       long dstTime = localTimeZone.useDaylightTime() ? 1 : 0;
205
206       result.put("sec", sec);
207       result.put("usec", microsec);
208       result.put("minuteswest", minutesWest);
209       result.put("dsttime", dstTime);
210
211       return result;
212     }
213   }
214
215   /**
216    * Returns the formatted date.
217    */

218   public String JavaDoc gmdate(String JavaDoc format,
219                @Optional("time()") long time)
220   {
221     return date(format, time, true);
222   }
223
224   /**
225    * Returns the formatted date.
226    */

227   public long gmmktime(@Optional("-1") int hour,
228                @Optional("-1") int minute,
229                @Optional("-1") int second,
230                @Optional("-1") int month,
231                @Optional("-1") int day,
232                @Optional("-1") int year)
233   {
234     QDate localDate = new QDate(false);
235     QDate gmtDate = new QDate(false);
236     long now = Alarm.getCurrentTime();
237
238     localDate.setLocalTime(now);
239
240     long gmtNow = localDate.getGMTTime();
241
242     gmtDate.setGMTTime(gmtNow);
243
244     if (hour >= 0)
245       gmtDate.setHour(hour);
246
247     if (minute >= 0)
248       gmtDate.setMinute(minute);
249
250     if (second >= 0)
251       gmtDate.setSecond(second);
252
253     if (month > 0)
254       gmtDate.setMonth(month - 1);
255
256     if (day > 0)
257       gmtDate.setDayOfMonth(day);
258
259     if (year > 0)
260       gmtDate.setYear(year);
261
262     return gmtDate.getGMTTime() / 1000L;
263   }
264
265   /**
266    * Returns the formatted date.
267    */

268   public String JavaDoc gmstrftime(String JavaDoc format,
269                @Optional("-1") long phpTime)
270   {
271     long time;
272
273     if (phpTime == -1)
274       time = Alarm.getCurrentTime();
275     else
276       time = 1000 * phpTime;
277
278     return QDate.formatGMT(time, format);
279   }
280
281   /**
282    * Convert from a gregorian date to a julian day.
283    */

284   public double gregoriantojd(int month, int day, int year)
285   {
286     if (month <= 2) {
287       year -= 1;
288       month += 12;
289     }
290
291     long a = year / 100;
292     long b = a / 4;
293     long c = 2 - a + b;
294     long e = (long) (365.25 * (year + 4716));
295     long f = (long) (30.6001 * (month + 1));
296
297     return (c + day + e + f - 1524.5);
298   }
299
300   /**
301    * Returns the formatted date.
302    */

303   private String JavaDoc date(String JavaDoc format,
304               long time,
305               boolean isGMT)
306   {
307     long now = 1000 * time;
308
309     QDate calendar = isGMT ? _gmtCalendar : _localCalendar;
310
311     synchronized (calendar) {
312       calendar.setGMTTime(now);
313
314       CharBuffer sb = new CharBuffer();
315       int len = format.length();
316
317       for (int i = 0; i < len; i++) {
318     char ch = format.charAt(i);
319
320     switch (ch) {
321     case 'd':
322       {
323         int day = calendar.getDayOfMonth();
324         sb.append(day / 10);
325         sb.append(day % 10);
326         break;
327       }
328
329     case 'D':
330       {
331         int day = calendar.getDayOfWeek();
332
333         sb.append(_shortDayOfWeek[day - 1]);
334         break;
335       }
336
337     case 'j':
338       {
339         int day = calendar.getDayOfMonth();
340         sb.append(day);
341         break;
342       }
343
344     case 'l':
345       {
346         int day = calendar.getDayOfWeek();
347
348         sb.append(_fullDayOfWeek[day]);
349         break;
350       }
351
352     case 'S':
353       {
354         int day = calendar.getDayOfMonth();
355
356         switch (day) {
357         case 1: case 21: case 31:
358           sb.append("st");
359           break;
360         case 2: case 22:
361           sb.append("nd");
362           break;
363         case 3: case 23:
364           sb.append("rd");
365           break;
366         default:
367           sb.append("th");
368           break;
369         }
370         break;
371       }
372
373     case 'w':
374       {
375         int day = calendar.getDayOfWeek();
376
377         sb.append(day);
378         break;
379       }
380
381     case 'z':
382       {
383         int day = calendar.getDayOfYear();
384
385         sb.append(day);
386         break;
387       }
388
389     case 'W':
390       {
391         int week = calendar.getWeek();
392
393         sb.append(week);
394         break;
395       }
396
397     case 'm':
398       {
399         int month = calendar.getMonth() + 1;
400         sb.append(month / 10);
401         sb.append(month % 10);
402         break;
403       }
404
405     case 'M':
406       {
407         int month = calendar.getMonth();
408         sb.append(_shortMonth[month]);
409         break;
410       }
411
412     case 'F':
413       {
414         int month = calendar.getMonth();
415         sb.append(_fullMonth[month]);
416         break;
417       }
418
419     case 'n':
420       {
421         int month = calendar.getMonth() + 1;
422         sb.append(month);
423         break;
424       }
425
426     case 't':
427       {
428         int days = calendar.getDaysInMonth();
429         sb.append(days);
430         break;
431       }
432
433     case 'Y':
434       {
435         int year = calendar.getYear();
436
437         sb.append((year / 1000) % 10);
438         sb.append((year / 100) % 10);
439         sb.append((year / 10) % 10);
440         sb.append((year) % 10);
441         break;
442       }
443
444     case 'y':
445       {
446         int year = calendar.getYear();
447
448         sb.append((year / 10) % 10);
449         sb.append((year) % 10);
450         break;
451       }
452
453     case 'L':
454       {
455         if (calendar.isLeapYear())
456           sb.append(1);
457         else
458           sb.append(0);
459         break;
460       }
461
462     case 'a':
463       {
464         int hour = calendar.getHour();
465
466         if (hour < 12)
467           sb.append("am");
468         else
469           sb.append("pm");
470         break;
471       }
472
473     case 'A':
474       {
475         int hour = calendar.getHour();
476
477         if (hour < 12)
478           sb.append("AM");
479         else
480           sb.append("PM");
481         break;
482       }
483
484     case 'g':
485       {
486         int hour = calendar.getHour() % 12;
487
488         if (hour == 0)
489           hour = 12;
490
491         sb.append(hour);
492         break;
493       }
494
495     case 'G':
496       {
497         int hour = calendar.getHour();
498
499         sb.append(hour);
500         break;
501       }
502
503     case 'h':
504       {
505         int hour = calendar.getHour() % 12;
506
507         if (hour == 0)
508           hour = 12;
509
510         sb.append(hour / 10);
511         sb.append(hour % 10);
512         break;
513       }
514
515     case 'H':
516       {
517         int hour = calendar.getHour();
518
519         sb.append(hour / 10);
520         sb.append(hour % 10);
521         break;
522       }
523
524     case 'i':
525       {
526         int minutes = calendar.getMinute();
527
528         sb.append(minutes / 10);
529         sb.append(minutes % 10);
530         break;
531       }
532
533     case 's':
534       {
535         int seconds = calendar.getSecond();
536
537         sb.append(seconds / 10);
538         sb.append(seconds % 10);
539         break;
540       }
541
542     case 'O':
543       {
544         long offset = calendar.getZoneOffset();
545
546         int minute = (int) (offset / (60 * 1000));
547
548         if (minute < 0)
549           sb.append('-');
550         else
551           sb.append('+');
552
553         sb.append((minute / 60) / 10);
554         sb.append((minute / 60) % 10);
555         sb.append((minute / 10) % 10);
556         sb.append(minute % 10);
557         break;
558       }
559
560     case 'I':
561       {
562         if (calendar.isDST())
563           sb.append('1');
564         else
565           sb.append('0');
566         break;
567       }
568
569     case 'T':
570       {
571         TimeZone JavaDoc zone = calendar.getLocalTimeZone();
572
573         sb.append(zone.getDisplayName(calendar.isDST(), TimeZone.SHORT));
574         break;
575       }
576
577     case 'Z':
578       {
579         long offset = calendar.getZoneOffset();
580
581         sb.append(offset / (1000));
582         break;
583       }
584
585     case 'c':
586       {
587         sb.append(calendar.printISO8601());
588         break;
589       }
590
591     case 'r':
592       {
593         sb.append(calendar.printDate());
594         break;
595       }
596
597     case 'U':
598       {
599         sb.append(now / 1000);
600         break;
601       }
602
603     case '\\':
604       sb.append(format.charAt(++i));
605       break;
606
607     default:
608       sb.append(ch);
609       break;
610     }
611       }
612
613       return sb.toString();
614     }
615   }
616
617   /**
618    * Returns the time including microseconds
619    */

620   public static Value microtime(@Optional boolean getAsFloat)
621   {
622     long now = Alarm.getExactTimeNanoseconds() / 1000;
623
624     if (getAsFloat) {
625       return new DoubleValue(((double) now) / 1e6);
626     }
627     else {
628       return (new StringBuilderValue()
629           .append(now % 1000000L / 1e6)
630           .append(' ')
631           .append(now / 1000000L));
632     }
633   }
634
635   /**
636    * Returns the formatted date.
637    */

638   public long mktime(Env env,
639                      @Optional("-1") int hour,
640              @Optional("-1") int minute,
641              @Optional("-1") int second,
642              @Optional("-1") int month,
643              @Optional("-1") int day,
644              @Optional("-1") int year,
645                      @Optional("-1") int isDST)
646   {
647     if (isDST != -1)
648       env.deprecatedArgument("isDST");
649
650     QDate date = new QDate(true);
651
652     long now = Alarm.getCurrentTime();
653
654     date.setLocalTime(now);
655
656     if (hour >= 0)
657       date.setHour(hour);
658
659     if (minute >= 0)
660       date.setMinute(minute);
661
662     if (second >= 0)
663       date.setSecond(second);
664
665     if (month > 0)
666       date.setMonth(month - 1);
667
668     if (day > 0)
669       date.setDayOfMonth(day);
670
671     if (year > 0)
672       date.setYear(year);
673
674     return date.getGMTTime() / 1000L;
675   }
676
677   /**
678    * Returns the formatted date.
679    */

680   public String JavaDoc strftime(String JavaDoc format,
681              @Optional("-1") long phpTime)
682   {
683     long time;
684
685     if (phpTime == -1)
686       time = Alarm.getCurrentTime();
687     else
688       time = 1000 * phpTime;
689
690     return QDate.formatLocal(time, format);
691   }
692
693   /**
694    * Parses the time
695    */

696   public Value strtotime(String JavaDoc timeString,
697              @Optional("-1") long now)
698   {
699     try {
700       if (now >= 0)
701     now = 1000L * now;
702       else
703     now = Alarm.getCurrentTime();
704
705       QDate date = new QDate(true);
706       date.setGMTTime(now);
707
708       if (timeString.equals("")) {
709     date.setHour(0);
710     date.setMinute(0);
711     date.setSecond(0);
712
713     return new LongValue(date.getGMTTime() / 1000L);
714       }
715
716       DateParser parser = new DateParser(timeString, date);
717
718       return new LongValue(parser.parse() / 1000L);
719     } catch (Exception JavaDoc e) {
720       log.log(Level.FINE, e.toString(), e);
721
722       return BooleanValue.FALSE;
723     }
724   }
725
726   /**
727    * Returns the current time in seconds.
728    */

729   public static long time()
730   {
731     return Alarm.getCurrentTime() / 1000L;
732   }
733
734   /**
735    * Convert from a julian day to unix
736    */

737   public long jdtounix(double jd)
738   {
739     long z = (long) (jd + 0.5);
740     long w = (long) ((z - 1867216.25) / 36524.25);
741     long x = (long) (w / 4);
742     long a = (long) (z + 1 + w - x);
743     long b = (long) (a + 1524);
744     long c = (long) ((b - 122.1) / 365.25);
745     long d = (long) (365.25 * c);
746     long e = (long) ((b - d) / 30.6001);
747     long f = (long) (30.6001 * e);
748
749     long day = b - d - f;
750     long month = e - 1;
751     long year = c - 4716;
752
753     if (month > 12) {
754       month -= 12;
755       year += 1;
756     }
757     
758     synchronized (_localCalendar) {
759       _localCalendar.setHour(0);
760       _localCalendar.setMinute(0);
761       _localCalendar.setSecond(0);
762       _localCalendar.setDayOfMonth((int) day);
763       _localCalendar.setMonth((int) (month - 1));
764       _localCalendar.setYear((int) year);
765
766       return _localCalendar.getLocalTime() / 1000L;
767     }
768   }
769
770   class DateParser {
771     private static final int INT = 1;
772     private static final int PERIOD = 2;
773     private static final int AGO = 3;
774     private static final int AM = 4;
775     private static final int PM = 5;
776     private static final int MONTH = 6;
777     private static final int WEEKDAY = 7;
778     private static final int UTC = 8;
779     
780     private static final int UNIT_YEAR = 1;
781     private static final int UNIT_MONTH = 2;
782     private static final int UNIT_FORTNIGHT = 3;
783     private static final int UNIT_WEEK = 4;
784     private static final int UNIT_DAY = 5;
785     private static final int UNIT_HOUR = 6;
786     private static final int UNIT_MINUTE = 7;
787     private static final int UNIT_SECOND = 8;
788     private static final int UNIT_NOW = 9;
789     
790     private static final int NULL_VALUE = Integer.MAX_VALUE;
791
792     private QDate _date;
793     
794     private String JavaDoc _s;
795     private int _index;
796     private int _length;
797     
798     private StringBuilder JavaDoc _sb = new StringBuilder JavaDoc();
799
800     private int _peekToken;
801     
802     private int _value;
803     private int _digits;
804     private int _unit;
805     private int _weekday;
806
807     private boolean _hasDate;
808     private boolean _hasTime;
809
810     DateParser(String JavaDoc s, QDate date)
811     {
812       _date = date;
813       _s = s;
814       _length = s.length();
815     }
816
817     long parse()
818     {
819       _value = NULL_VALUE;
820       _unit = 0;
821     
822       while (true) {
823     int token = nextToken();
824
825     if (token == '-') {
826       token = nextToken();
827
828       if (token == INT)
829         _value = -_value;
830       else {
831         _peekToken = token;
832         continue;
833       }
834     }
835
836     if (token < 0) {
837       return _date.getGMTTime();
838     }
839     else if (token == INT) {
840       int digits = _digits;
841       int value = _value;
842       
843       token = nextToken();
844
845       if (token == PERIOD) {
846         parsePeriod();
847       }
848       else if (token == ':') {
849         parseTime();
850         _hasTime = true;
851       }
852       else if (token == '-') {
853         parseISODate(value);
854         _hasDate = true;
855       }
856       else if (token == '/') {
857         parseUSDate(value);
858         _hasDate = true;
859       }
860       else if (token == MONTH) {
861         parseDayMonthDate(value);
862         _hasDate = true;
863       }
864       else {
865         _peekToken = token;
866
867         parseBareInt(value, digits);
868       }
869     }
870     else if (token == PERIOD) {
871       parsePeriod();
872     }
873     else if (token == WEEKDAY) {
874       addWeekday(_value, _weekday);
875       _value = NULL_VALUE;
876     }
877     else if (token == MONTH) {
878       parseMonthDate(_value);
879       _hasDate = true;
880     }
881     else if (token == '@') {
882       token = nextToken();
883
884       if (token == INT) {
885         int value = _value;
886         _value = NULL_VALUE;
887
888         _date.setGMTTime(value * 1000L);
889
890         token = nextToken();
891         if (token == '.') {
892           token = nextToken();
893
894           if (token != INT)
895         _peekToken = token;
896         }
897         else {
898           _peekToken = token;
899         }
900       }
901     }
902       }
903     }
904
905     private void parsePeriod()
906     {
907       int value = _value;
908       int unit = _unit;
909
910       _value = NULL_VALUE;
911       _unit = 0;
912
913       int token = nextToken();
914       if (token == AGO)
915     value = -value;
916       else
917     _peekToken = token;
918
919       addTime(value, unit);
920     }
921
922     private void parseISODate(int value1)
923     {
924       int year = _date.getYear();
925       int month = 0;
926       int day = 0;
927       
928       if (value1 < 0)
929     value1 = - value1;
930       
931       int token = nextToken();
932
933       int value2 = 0;
934       
935       if (token == INT) {
936     value2 = _value;
937     _value = NULL_VALUE;
938       }
939       else {
940     _peekToken = token;
941     return;
942       }
943       
944       token = nextToken();
945
946       if (token == '-') {
947     token = nextToken();
948
949     if (token == INT) {
950       if (value1 < 0)
951         _date.setYear(value1);
952       else if (value1 <= 68)
953         _date.setYear(2000 + value1);
954       else if (value1 < 100)
955         _date.setYear(1900 + value1);
956       else
957         _date.setYear(value1);
958       
959       _date.setMonth(value2 - 1);
960       _date.setDayOfMonth(_value);
961     }
962     else {
963       _date.setMonth(value1 - 1);
964       _date.setDayOfMonth(value2);
965       
966       _peekToken = token;
967     }
968       }
969       else {
970     _date.setMonth(value1 - 1);
971     _date.setDayOfMonth(value2);
972       
973     _peekToken = token;
974       }
975     }
976
977     private void parseUSDate(int value1)
978     {
979       int year = _date.getYear();
980       int month = 0;
981       int day = 0;
982       
983       if (value1 < 0)
984     value1 = - value1;
985       
986       int token = nextToken();
987
988       int value2 = 0;
989       
990       if (token == INT) {
991     value2 = _value;
992       }
993       else {
994     _peekToken = token;
995     return;
996       }
997       
998       _value = NULL_VALUE;
999       token = nextToken();
1000
1001      if (token == '/') {
1002    token = nextToken();
1003
1004    if (token == INT) {
1005      _date.setMonth(value1 - 1);
1006      _date.setDayOfMonth(value2);
1007      
1008      if (_value < 0)
1009        _date.setYear(_value);
1010      else if (_value <= 68)
1011        _date.setYear(2000 + _value);
1012      else if (_value < 100)
1013        _date.setYear(1900 + _value);
1014      else
1015        _date.setYear(_value);
1016    }
1017    else {
1018      _date.setMonth(value1 - 1);
1019      _date.setDayOfMonth(value2);
1020      
1021      _peekToken = token;
1022    }
1023    _value = NULL_VALUE;
1024      }
1025      else {
1026    _date.setMonth(value1 - 1);
1027    _date.setDayOfMonth(value2);
1028      
1029    _peekToken = token;
1030      }
1031    }
1032
1033    private void parseDayMonthDate(int value1)
1034    {
1035      int year = _date.getYear();
1036      int month = 0;
1037      int day = 0;
1038      
1039      if (value1 < 0)
1040    value1 = - value1;
1041
1042      int value2 = _value;
1043
1044      _value = NULL_VALUE;
1045      int token = nextToken();
1046
1047      if (token == '-') {
1048    _value = NULL_VALUE;
1049    token = nextToken();
1050      }
1051
1052      if (token == INT) {
1053    _date.setDayOfMonth(value1);
1054    _date.setMonth(value2 - 1);
1055      
1056    if (_value < 0)
1057      _date.setYear(_value);
1058    else if (_value <= 68)
1059      _date.setYear(2000 + _value);
1060    else if (_value < 100)
1061      _date.setYear(1900 + _value);
1062    else
1063      _date.setYear(_value);
1064    
1065    _value = NULL_VALUE;
1066      }
1067      else {
1068    _date.setDayOfMonth(value1);
1069    _date.setMonth(value2 - 1);
1070      
1071    _peekToken = token;
1072      }
1073    }
1074
1075    private void parseMonthDate(int value1)
1076    {
1077      if (value1 < 0)
1078    value1 = - value1;
1079
1080      _value = NULL_VALUE;
1081      int token = nextToken();
1082
1083      if (token == '-') {
1084    _value = NULL_VALUE;
1085    token = nextToken();
1086      }
1087
1088      if (token == INT) {
1089    int value2 = _value;
1090
1091    _value = NULL_VALUE;
1092    token = nextToken();
1093    if (token == '-') {
1094      _value = NULL_VALUE;
1095      token = nextToken();
1096    }
1097
1098    if (token == INT) {
1099      _date.setMonth(value1 - 1);
1100      _date.setDayOfMonth(value2);
1101      
1102      if (_value < 0)
1103        _date.setYear(_value);
1104      else if (_value <= 68)
1105        _date.setYear(2000 + _value);
1106      else if (_value < 100)
1107        _date.setYear(1900 + _value);
1108      else
1109        _date.setYear(_value);
1110      
1111      _value = NULL_VALUE;
1112    }
1113    else {
1114      _date.setMonth(value1 - 1);
1115      _date.setDayOfMonth(value2);
1116
1117      _peekToken = token;
1118    }
1119      }
1120      else {
1121    _date.setMonth(value1 - 1);
1122      
1123    _peekToken = token;
1124      }
1125    }
1126
1127    private void parseTime()
1128    {
1129      int hour = _value;
1130      _value = NULL_VALUE;
1131
1132      if (hour < 0)
1133    hour = - hour;
1134
1135      _date.setHour(hour);
1136      _date.setMinute(0);
1137      _date.setSecond(0);
1138      _date.setMillisecond(0);
1139      
1140      int token = nextToken();
1141      
1142      if (token == INT) {
1143    _date.setMinute(_value);
1144    _value = NULL_VALUE;
1145      }
1146      else {
1147    _peekToken = token;
1148    return;
1149      }
1150
1151      token = nextToken();
1152
1153      if (token == ':') {
1154    token = nextToken();
1155      
1156    if (token == INT) {
1157      _date.setSecond(_value);
1158      _value = NULL_VALUE;
1159    }
1160    else {
1161      _peekToken = token;
1162      return;
1163    }
1164
1165    token = nextToken();
1166
1167    if (token == '.') { // milliseconds
1168
token = nextToken();
1169
1170      _value = NULL_VALUE;
1171      if (token != INT) {
1172        _peekToken = token;
1173        return;
1174      }
1175    }
1176      }
1177
1178      if (token == AM) {
1179    hour = _date.getHour();
1180
1181    if (hour == 12)
1182      _date.setHour(0);
1183      }
1184      else if (token == PM) {
1185    hour = _date.getHour();
1186
1187    if (hour == 12)
1188      _date.setHour(12);
1189    else
1190      _date.setHour(hour + 12);
1191      }
1192      else
1193    _peekToken = token;
1194
1195      parseTimezone();
1196    }
1197
1198    private void parseTimezone()
1199    {
1200      int token = nextToken();
1201      int sign = 1;
1202      boolean hasUTC = false;
1203
1204      if (token == UTC) {
1205    token = nextToken();
1206    
1207    hasUTC = true;
1208      }
1209
1210      if (token == '-')
1211    sign = -1;
1212      else if (token == '+')
1213    sign = 1;
1214      else {
1215    _peekToken = token;
1216
1217    if (hasUTC)
1218      _date.setGMTTime(_date.getGMTTime() + _date.getZoneOffset());
1219    
1220    return;
1221      }
1222
1223      int offset = 0;
1224
1225      token = nextToken();
1226      if (token != INT) {
1227    _peekToken = token;
1228
1229    if (hasUTC)
1230      _date.setGMTTime(_date.getGMTTime() + _date.getZoneOffset());
1231      
1232    return;
1233      }
1234      else if (_digits == 4) {
1235    int value = sign * _value;
1236    _value = NULL_VALUE;
1237
1238    _date.setGMTTime(_date.getGMTTime() - value * 60000L + _date.getZoneOffset());
1239    return;
1240      }
1241      else if (_digits == 2) {
1242    int value = _value;
1243
1244    token = nextToken();
1245
1246    if (token != ':') {
1247      _value = sign * _value;
1248      _peekToken = token;
1249
1250      if (hasUTC)
1251        _date.setGMTTime(_date.getGMTTime() + _date.getZoneOffset());
1252      return;
1253    }
1254
1255    value = sign * (100 * value + _value);
1256
1257    _date.setGMTTime(_date.getGMTTime() - value * 60000L + _date.getZoneOffset());
1258    return;
1259      }
1260      else {
1261    _value = sign * _value;
1262    _peekToken = token;
1263    
1264    if (hasUTC)
1265      _date.setGMTTime(_date.getGMTTime() + _date.getZoneOffset());
1266    
1267    return;
1268      }
1269    }
1270
1271    private void addTime(int value, int unit)
1272    {
1273      if (value == NULL_VALUE)
1274    value = 1;
1275      else if (value == -NULL_VALUE)
1276    value = -1;
1277      
1278      switch (unit) {
1279      case UNIT_YEAR:
1280    _date.setYear(_date.getYear() + value);
1281    break;
1282      case UNIT_MONTH:
1283    _date.setMonth(_date.getMonth() + value);
1284    break;
1285      case UNIT_FORTNIGHT:
1286    _date.setGMTTime(_date.getGMTTime() + 14 * DAY * value);
1287    break;
1288      case UNIT_WEEK:
1289    _date.setGMTTime(_date.getGMTTime() + 7 * DAY * value);
1290    break;
1291      case UNIT_DAY:
1292    _date.setGMTTime(_date.getGMTTime() + DAY * value);
1293    break;
1294      case UNIT_HOUR:
1295    _date.setGMTTime(_date.getGMTTime() + HOUR * value);
1296    break;
1297      case UNIT_MINUTE:
1298    _date.setGMTTime(_date.getGMTTime() + MINUTE * value);
1299    break;
1300      case UNIT_SECOND:
1301    _date.setGMTTime(_date.getGMTTime() + 1000L * value);
1302    break;
1303      }
1304    }
1305
1306    private void addWeekday(int value, int weekday)
1307    {
1308      if (value == NULL_VALUE)
1309    value = 0;
1310      else if (value == -NULL_VALUE)
1311    value = -1;
1312
1313      _date.setDayOfMonth(_date.getDayOfMonth() +
1314              (8 + weekday - _date.getDayOfWeek()) % 7 +
1315              7 * value);
1316    }
1317
1318    private void parseBareInt(int value, int digits)
1319    {
1320      if (digits == 8 && ! _hasDate) {
1321    _hasDate = true;
1322
1323    _date.setYear(value / 10000);
1324    _date.setMonth((value / 100 % 12) - 1);
1325    _date.setDayOfMonth(value % 100);
1326      }
1327      else if (digits == 6 && ! _hasTime) {
1328    _hasTime = true;
1329    _date.setHour(value / 10000);
1330    _date.setMinute(value / 100 % 100);
1331    _date.setSecond(value % 100);
1332
1333    parseTimezone();
1334      }
1335      else if (digits == 4 && ! _hasTime) {
1336    _hasTime = true;
1337    _date.setHour(value / 100);
1338    _date.setMinute(value % 100);
1339    _date.setSecond(0);
1340    parseTimezone();
1341      }
1342      else if (digits == 2 && ! _hasTime) {
1343    _hasTime = true;
1344    _date.setHour(value);
1345    _date.setMinute(0);
1346    _date.setSecond(0);
1347    parseTimezone();
1348      }
1349
1350      int token = nextToken();
1351      if (token == '.') {
1352    _value = NULL_VALUE;
1353    token = nextToken();
1354
1355    if (token == INT)
1356      _value = NULL_VALUE;
1357    else
1358      _peekToken = token;
1359      }
1360      else
1361    _peekToken = token;
1362    }
1363
1364    int nextToken()
1365    {
1366      if (_peekToken > 0) {
1367    int token = _peekToken;
1368    _peekToken = 0;
1369    return token;
1370      }
1371      
1372      while (true) {
1373    skipSpaces();
1374      
1375    int ch = read();
1376
1377    if (ch < 0)
1378      return -1;
1379    else if (ch == '-')
1380      return '-';
1381    else if (ch == '+')
1382      return '+';
1383    else if (ch == ':')
1384      return ':';
1385    else if (ch == '.')
1386      return '.';
1387    else if (ch == '/')
1388      return '/';
1389    else if (ch == '@')
1390      return '@';
1391    else if ('0' <= ch && ch <= '9') {
1392      int value = 0;
1393      int digits = 0;
1394
1395      for (; '0' <= ch && ch <= '9'; ch = read()) {
1396        digits++;
1397        value = 10 * value + ch - '0';
1398      }
1399
1400      _value = value;
1401      _digits = digits;
1402
1403      unread();
1404
1405      return INT;
1406    }
1407    else if ('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z') {
1408      _sb.setLength(0);
1409    
1410      for (;
1411           'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '.';
1412           ch = read()) {
1413        _sb.append(Character.toLowerCase((char) ch));
1414      }
1415
1416      unread();
1417
1418      String JavaDoc s = _sb.toString();
1419
1420      return parseString(s);
1421    }
1422    else {
1423      // skip
1424
}
1425      }
1426    }
1427
1428    private int parseString(String JavaDoc s)
1429    {
1430      if (s.endsWith("."))
1431    s = s.substring(0, s.length() - 1);
1432      
1433      if ("now".equals(s) ||
1434      "today".equals(s)) {
1435    _value = 0;
1436    _unit = UNIT_NOW;
1437    return PERIOD;
1438      }
1439      else if ("last".equals(s)) {
1440    _value = -1;
1441    return INT;
1442      }
1443      else if ("this".equals(s)) {
1444    _value = 0;
1445    return INT;
1446      }
1447      else if ("am".equals(s) || "a.m".equals(s)) {
1448    return AM;
1449      }
1450      else if ("pm".equals(s) || "p.m".equals(s)) {
1451    return PM;
1452      }
1453      else if ("next".equals(s)) {
1454    _value = 1;
1455    return INT;
1456      }
1457      else if ("third".equals(s)) {
1458    _value = 3;
1459    return INT;
1460      }
1461      else if ("fourth".equals(s)) {
1462    _value = 4;
1463    return INT;
1464      }
1465      else if ("fifth".equals(s)) {
1466    _value = 5;
1467    return INT;
1468      }
1469      else if ("sixth".equals(s)) {
1470    _value = 6;
1471    return INT;
1472      }
1473      else if ("seventh".equals(s)) {
1474    _value = 7;
1475    return INT;
1476      }
1477      else if ("eighth".equals(s)) {
1478    _value = 8;
1479    return INT;
1480      }
1481      else if ("ninth".equals(s)) {
1482    _value = 9;
1483    return INT;
1484      }
1485      else if ("tenth".equals(s)) {
1486    _value = 10;
1487    return INT;
1488      }
1489      else if ("eleventh".equals(s)) {
1490    _value = 11;
1491    return INT;
1492      }
1493      else if ("twelfth".equals(s)) {
1494    _value = 12;
1495    return INT;
1496      }
1497      else if ("yesterday".equals(s)) {
1498    _value = -1;
1499    _unit = UNIT_DAY;
1500    return PERIOD;
1501      }
1502      else if ("tomorrow".equals(s)) {
1503    _value = 1;
1504    _unit = UNIT_DAY;
1505    return PERIOD;
1506      }
1507      else if ("ago".equals(s)) {
1508    return AGO;
1509      }
1510      else if ("year".equals(s) || "years".equals(s)) {
1511    _unit = UNIT_YEAR;
1512    return PERIOD;
1513      }
1514      else if ("month".equals(s) || "months".equals(s)) {
1515    _unit = UNIT_MONTH;
1516    return PERIOD;
1517      }
1518      else if ("fortnight".equals(s) || "fortnights".equals(s)) {
1519    _unit = UNIT_FORTNIGHT;
1520    return PERIOD;
1521      }
1522      else if ("week".equals(s) || "weeks".equals(s)) {
1523    _unit = UNIT_WEEK;
1524    return PERIOD;
1525      }
1526      else if ("day".equals(s) || "days".equals(s)) {
1527    _unit = UNIT_DAY;
1528    return PERIOD;
1529      }
1530      else if ("hour".equals(s) || "hours".equals(s)) {
1531    _unit = UNIT_HOUR;
1532    return PERIOD;
1533      }
1534      else if ("minute".equals(s) || "minutes".equals(s)) {
1535    _unit = UNIT_MINUTE;
1536    return PERIOD;
1537      }
1538      else if ("second".equals(s) || "seconds".equals(s)) {
1539    _unit = UNIT_SECOND;
1540    return PERIOD;
1541      }
1542      else if ("second".equals(s) || "seconds".equals(s)) {
1543    _unit = UNIT_SECOND;
1544    return PERIOD;
1545      }
1546      else if ("january".equals(s) || "jan".equals(s)) {
1547    _value = 1;
1548    return MONTH;
1549      }
1550      else if ("february".equals(s) || "feb".equals(s)) {
1551    _value = 2;
1552    return MONTH;
1553      }
1554      else if ("march".equals(s) || "mar".equals(s)) {
1555    _value = 3;
1556    return MONTH;
1557      }
1558      else if ("april".equals(s) || "apr".equals(s)) {
1559    _value = 4;
1560    return MONTH;
1561      }
1562      else if ("may".equals(s)) {
1563    _value = 5;
1564    return MONTH;
1565      }
1566      else if ("june".equals(s) || "jun".equals(s)) {
1567    _value = 6;
1568    return MONTH;
1569      }
1570      else if ("july".equals(s) || "jul".equals(s)) {
1571    _value = 7;
1572    return MONTH;
1573      }
1574      else if ("august".equals(s) || "aug".equals(s)) {
1575    _value = 8;
1576    return MONTH;
1577      }
1578      else if ("september".equals(s) || "sep".equals(s) || "sept".equals(s)) {
1579    _value = 9;
1580    return MONTH;
1581      }
1582      else if ("october".equals(s) || "oct".equals(s)) {
1583    _value = 10;
1584    return MONTH;
1585      }
1586      else if ("november".equals(s) || "nov".equals(s)) {
1587    _value = 11;
1588    return MONTH;
1589      }
1590      else if ("december".equals(s) || "dec".equals(s)) {
1591    _value = 12;
1592    return MONTH;
1593      }
1594      else if ("sunday".equals(s) || "sun".equals(s)) {
1595    _weekday = 0;
1596    return WEEKDAY;
1597      }
1598      else if ("monday".equals(s) || "mon".equals(s)) {
1599    _weekday = 1;
1600    return WEEKDAY;
1601      }
1602      else if ("tuesday".equals(s) || "tue".equals(s) || "tues".equals(s)) {
1603    _weekday = 2;
1604    return WEEKDAY;
1605      }
1606      else if ("wednesday".equals(s) || "wed".equals(s) ||
1607           "wednes".equals(s)) {
1608    _weekday = 3;
1609    return WEEKDAY;
1610      }
1611      else if ("thursday".equals(s) || "thu".equals(s) ||
1612           "thur".equals(s) || "thurs".equals(s)) {
1613    _weekday = 4;
1614    return WEEKDAY;
1615      }
1616      else if ("friday".equals(s) || "fri".equals(s)) {
1617    _weekday = 5;
1618    return WEEKDAY;
1619      }
1620      else if ("saturday".equals(s) || "sat".equals(s)) {
1621    _weekday = 6;
1622    return WEEKDAY;
1623      }
1624      else if ("z".equals(s) || "gmt".equals(s) || "utc".equals(s)) {
1625    return UTC;
1626      }
1627      else
1628    return 0;
1629    }
1630
1631    private void skipSpaces()
1632    {
1633      while (true) {
1634    int ch = read();
1635
1636    if (Character.isWhitespace((char) ch)) {
1637      continue;
1638    }
1639    else if (ch == '(') {
1640      for (ch = read(); ch > 0 && ch != ')'; ch = read()) {
1641      }
1642    }
1643    else {
1644      unread();
1645      return;
1646    }
1647      }
1648    }
1649
1650    int read()
1651    {
1652      if (_index < _length)
1653    return _s.charAt(_index++);
1654      else {
1655    _index++;
1656    return -1;
1657      }
1658    }
1659
1660    void unread()
1661    {
1662      _index--;
1663    }
1664  }
1665}
1666
1667
Popular Tags