Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/tripi/asp/AspDate.java


1   /**
2    * ArrowHead ASP Server 
3    * This is a source file for the ArrowHead ASP Server - an 100% Java
4    * VBScript interpreter and ASP server.
5    *
6    * For more information, see http://www.tripi.com/arrowhead
7    *
8    * Copyright (C) 2002  Terence Haddock
9    *
10   * This program is free software; you can redistribute it and/or modify
11   * it under the terms of the GNU General Public License as published by
12   * the Free Software Foundation; either version 2 of the License, or
13   * (at your option) any later version.
14   *
15   * This program is distributed in the hope that it will be useful,
16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   * GNU General Public License for more details.
19   *
20   * You should have received a copy of the GNU General Public License
21   * along with this program; if not, write to the Free Software
22   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23   *
24   */
25  package com.tripi.asp;
26  
27  import java.text.DateFormat;
28  import java.text.DateFormatSymbols;
29  import java.text.SimpleDateFormat;
30  import java.util.Calendar;
31  import java.util.Date;
32  import java.util.GregorianCalendar;
33  
34  import jregex.Matcher;
35  import jregex.Pattern;
36  import jregex.RETokenizer;
37  
38  import org.apache.log4j.Category;
39  
40  /**
41   * The AspDate class contains the special code needed for handling ASP
42   * dates. This class can process most date format, and can be configured
43   * for the default month, day, year ordering.
44   * 
45   * @author Terence Haddock
46   * @version 0.9
47   */
48  public class AspDate
49  {
50      /** Debugging class */
51      private static final Category DBG = Category.getInstance(AspDate.class);
52  
53      /** Month bit field */
54      static final int MONTH = 0x10;
55  
56      /** Day bit field */
57      static final int DAY = 0x8;
58  
59      /** Year bit field */
60      static final int YEAR = 0x4;
61  
62      /** Time bit field */
63      static final int TIME = 0x2;
64  
65      /** AM/PM bit field */
66      static final int AMPM = 0x1;
67  
68      /** Field contains the current default order of the month, day, year fields */
69      protected static String order = "MDY";
70  
71      /** The current date/time values as a calendar object */
72      protected Calendar    cal = new GregorianCalendar();
73  
74      /** Does this object hold a time value? */
75      protected boolean   hasTime = false;
76  
77      /** Does this object hold a date value? */
78      protected boolean   hasDate = false;
79  
80      /** Long date/time format */
81      static DateFormat longDateTimeFormat =
82          new SimpleDateFormat("M/d/yyyy h:mm:ss aa");
83  
84      /** Long date format */
85      static DateFormat longDateFormat =
86          new SimpleDateFormat("EEEE, MMMM d, yyyy");
87  
88      /** Short date format */
89      static DateFormat shortDateFormat = new SimpleDateFormat("M/d/yyyy");
90  
91      /** Long time format */
92      static DateFormat longTimeFormat = new SimpleDateFormat("h:mm:ss aa");
93  
94      /** Short time format */
95      static DateFormat shortTimeFormat = new SimpleDateFormat("H:mm");
96  
97      /**
98       * This constructor creates an AspDate object from a generic time
99       * string.
100      * @param datestr date/time string
101      * @throws AspException on error
102      */
103     public AspDate(String datestr) throws AspException
104     {
105         /* This is the tokenizer we will use */
106         final Pattern p = new Pattern("[, \t\\-\\\\/]+");
107         RETokenizer tok = p.tokenizer(datestr);
108         String parts[] = tok.split();
109         /* match will hold the type of data this string can represent in a
110            bit pattern */
111         int match[] = new int[parts.length];
112         for (int i = 0; i < parts.length; i++) {
113             if (DBG.isDebugEnabled())
114                 DBG.debug("parts[" + i + "] = " + parts[i]);
115             if (isNumber(parts[i])) {
116                 int iVal = Integer.parseInt(parts[i]);
117                 if (iVal > 0 && iVal <= 12) {
118                     match[i] = MONTH | DAY | YEAR;
119                 } else if (iVal > 12 && iVal <= 31) {
120                     match[i] = DAY | YEAR;
121                 } else {
122                     match[i] = YEAR;
123                 }
124             } else if (getMonthString(parts[i]) != -1) {
125                 match[i] = MONTH;
126             } else if (isTimeString(parts[i])) {
127                 match[i] = TIME;
128             } else if (parts[i].equalsIgnoreCase("am") ||
129                     parts[i].equalsIgnoreCase("pm")) {
130                 match[i] = AMPM;
131             } else {
132                 throw new AspCastException("Cannot convert string \"" +
133                     datestr + "\" to date");
134             }
135         }
136         if (DBG.isDebugEnabled()) {
137             DBG.debug("Before logical elimination: ");
138             for (int i = 0; i < parts.length; i++) {
139                 DBG.debug("match[" + parts[i] + "] = " + match[i]);
140             }
141         }
142         /* From the bit patterns, perform a logical elimination of the
143            match state */
144         int bit = 1;
145         while (bit <= (MONTH|DAY|YEAR|TIME|AMPM)) {
146             for (int i = 0; i < parts.length; i++) {
147                 if (match[i] == bit) {
148                     if (DBG.isDebugEnabled()) DBG.debug("best for bit " + bit
149                         + ": " + i);
150                     for (int j = 0 ; j < parts.length; j++)
151                         if (j != i) match[j] &= ~bit;
152                     break;
153                 }
154             }
155             bit*=2;
156         }
157         if (DBG.isDebugEnabled()) {
158             DBG.debug("After logical elimination: ");
159             for (int i = 0; i < parts.length; i++) {
160                 DBG.debug("match[" + parts[i] + "] = " + match[i]);
161             }
162         }
163         /* Handle the MDY ordering for the last elimination */
164         for (int k = 0; k < 3; k++) {
165             if (order.charAt(k)=='M') bit = MONTH;
166             else if (order.charAt(k)=='D') bit = DAY;
167             else if (order.charAt(k)=='Y') bit = YEAR;
168             if (DBG.isDebugEnabled()) DBG.debug("Bit: " + bit);
169             for (int i = 0 ; i < parts.length; i++) {
170                 if ((match[i] & bit) == bit) {
171                     for (int j = 0; j < parts.length; j++)
172                         if (j != i) match[j] &= ~bit;
173                     match[i] = bit;
174                     break;
175                 }
176             }
177         }
178         if (DBG.isDebugEnabled()) {
179             DBG.debug("After ordering: ");
180             for (int i = 0; i < parts.length; i++) {
181                 DBG.debug("match[" + parts[i] + "] = " + match[i]);
182             }
183         }
184         /* Get the actual data which corresponds to the month,day,year fields */
185         cal.set(Calendar.HOUR_OF_DAY, 0);
186         cal.set(Calendar.MINUTE, 0);
187         cal.set(Calendar.SECOND, 0);
188         cal.set(Calendar.MILLISECOND, 0);
189         for (int i = 0; i < parts.length ; i++)
190         {
191             if (match[i] == MONTH) {
192                 int month;
193                 if (Character.isLetter(parts[i].charAt(0))) {
194                     month = getMonthString(parts[i]);
195                 } else {
196                     month = Integer.parseInt(parts[i]) - 1;
197                 }
198                 cal.set(Calendar.MONTH, month);
199                 hasDate = true;
200             } else if (match[i] == DAY) {
201                 int day = Integer.parseInt(parts[i]);
202                 cal.set(Calendar.DAY_OF_MONTH, day);
203                 hasDate = true;
204             } else if (match[i] == YEAR) {
205                 int year = Integer.parseInt(parts[i]);
206                 if (year > 50 && year < 100) {
207                     year+=1900;
208                 } else if (year < 100) {
209                     year+=2000;
210                 }
211                 cal.set(Calendar.YEAR, year);
212                 hasDate = true;
213             } else if (match[i] == TIME) {
214                 /* Check if a time is included */
215                 if (i < (match.length - 1) && match[i+1] == AMPM) {
216                     parseTime(parts[i] + parts[i + 1]);
217                 } else {
218                     parseTime(parts[i]);
219                 }
220             } else if (match[i] == AMPM) {
221                 if (i == 0 || match[i - 1] != TIME) {
222                     /* AM/PM has to be after a time */
223                     throw new AspCastException("Cannot convert string \"" +
224                         datestr + "\" to date");
225                 }
226             } else {
227                 /* A part did not match */
228                 throw new AspCastException("Cannot convert string \"" +
229                     datestr + "\" to date");
230             }
231         }
232         if (!hasDate)
233         {
234             cal.set(Calendar.MONTH, 11);
235             cal.set(Calendar.DAY_OF_MONTH, 30);
236             cal.set(Calendar.YEAR, 1899);
237         }
238     }
239 
240     /**
241      * This constructor creates an AspDate object from a Java Date object.
242      * @param date Java date object
243      */
244     public AspDate(Date date)
245     {
246         this(date, true, true);
247     }
248 
249     /**
250      * This constructor creates an AspDate object from a Java Date object,
251      * optionally setting the date and time values.
252      * @param javaDate Java date object
253      * @param hasTime has a time value?
254      * @param hasDate has a date value?
255      */
256     public AspDate(Date javaDate, boolean hasTime, boolean hasDate)
257     {
258         cal.setTime(javaDate);
259         this.hasTime = hasTime;
260         this.hasDate = hasDate;
261         if (!hasTime) {
262             cal.set(Calendar.HOUR_OF_DAY, 0);
263             cal.set(Calendar.MINUTE, 0);
264             cal.set(Calendar.SECOND, 0);
265             cal.set(Calendar.MILLISECOND, 0);
266         }
267         if (!hasDate) {
268             cal.set(Calendar.MONTH, 11);
269             cal.set(Calendar.DAY_OF_MONTH, 30);
270             cal.set(Calendar.YEAR, 1899);
271         }
272     }
273 
274     /**
275      * This constructor creates an AspDate object from a Java calendar object.
276      * @param cal Java calendar object
277      */
278     public AspDate(Calendar cal)
279     {
280         this(cal, true, true);
281     }
282 
283     /**
284      * This constructor creates an AspDate object from a Java Calendar object,
285      * optionally setting the date and time values.
286      * @param javaCal Java calendar object
287      * @param hasTime has a time value?
288      * @param hasDate has a date value?
289      */
290     public AspDate(Calendar javaCal, boolean hasTime, boolean hasDate)
291     {
292         this(javaCal.getTime(), hasTime, hasDate);
293     }
294 
295     /**
296      * Constructor set with specific time settings.
297      * @param month Month setting
298      * @param day Day setting
299      * @param year Year setting
300      * @param hour Hour setting
301      * @param minute Minute setting
302      * @param second Second setting
303      */
304     protected AspDate(int month, int day, int year, int hour, int minute, int second)
305     {
306         cal.set(Calendar.HOUR_OF_DAY, 0);
307         cal.set(Calendar.MINUTE, 0);
308         cal.set(Calendar.SECOND, 0);
309         cal.set(Calendar.MILLISECOND, 0);
310         cal.set(Calendar.MONTH, 11);
311         cal.set(Calendar.DAY_OF_MONTH, 30);
312         cal.set(Calendar.YEAR, 1899);
313         if (month != -1)
314         {
315             cal.set(Calendar.MONTH, month);
316             hasDate = true;
317         }
318         if (day != -1)
319         {
320             cal.set(Calendar.DAY_OF_MONTH, day);
321             hasDate = true;
322         }
323         if (year != -1)
324         {
325             cal.set(Calendar.YEAR, year);
326             hasDate = true;
327         }
328         if (hour != -1)
329         {
330             cal.set(Calendar.HOUR_OF_DAY, hour);
331             hasTime = true;
332         }
333         if (minute != -1)
334         {
335             cal.set(Calendar.MINUTE, minute);
336             hasTime = true;
337         }
338         if (second != -1)
339         {
340             cal.set(Calendar.SECOND, second);
341             hasTime = true;
342         }
343     }
344 
345     /**
346      * Constructor set with specific date-only settings.
347      * @param month Month setting
348      * @param day Day setting
349      * @param year Year setting
350      */
351     protected AspDate(int month, int day, int year)
352     {
353         this(month, day, year, -1, -1, -1);
354     }
355 
356     /**
357      * This function determines if the specified string contains a number
358      * @param str String to test
359      * @return true if the value is a number, false otherwise
360      */
361     private static boolean isNumber(String str)
362     {
363         char ch[] = str.toCharArray();
364         for (int x = 0; x < ch.length ; x++)
365         {
366             if (!Character.isDigit(ch[x])) return false;
367         }
368         return true;
369     }
370 
371     /**
372      * This funtion obtains from a string, the month the string corresponds
373      * to. Uses the build-in DateFormatSymbols class to match strings to
374      * months.
375      * @param str String to convert to month number.
376      * @return number of the month from 0 to 11, or -1 if the string is
377      * not recognized
378      */
379     private static int getMonthString(String str)
380     {
381         DateFormatSymbols format = new DateFormatSymbols();
382         String months[] = format.getShortMonths();
383         String mon = str.toLowerCase();
384         for (int i = 0; i < 12; i++)
385             if (mon.startsWith(months[i].toLowerCase())) return i;
386         return -1;
387     }
388 
389     /**
390      * This function attempts to determine if the given string is a time
391      * string.
392      * @param str string to check for time string
393      * @return true if the string is a time string, false otherwise
394      * @throws AspException on error
395      */
396     public static boolean isTimeString(String str) throws AspException
397     {
398         Pattern p = new Pattern("^[0-9]{1,2}:[0-9]{1,2}" +
399             "(:[0-9]{1,2}(\\.[0-9]{1,2})?)?([aApP][mM])?$");
400         Matcher m = p.matcher(str);
401         if (m.matches()) return true;
402         return false;
403     }
404 
405     /**
406      * This function parses the given string into hour, minute, second,
407      * and sets the internal variables accordingly.
408      * @param str Time string to parse
409      * @throws AspException on error
410      */
411     protected void parseTime(String str) throws AspException
412     {
413         final Pattern p = new Pattern("^([0-9]{1,2}):([0-9]{1,2})" +
414             "(:([0-9]{1,2})(\\.[0-9]{1,2})?)?([aApP][mM])?$");
415         Matcher m = p.matcher(str);
416 
417         if (!m.find()) {
418             throw new AspCastException("Cannot convert string \"" +
419                 str + "\" to time");
420         }
421 
422         hasTime = true;
423         int hour = Integer.parseInt(m.group(1));
424         int minute = Integer.parseInt(m.group(2));
425         int second = 0;
426         if (m.group(4) != null) {
427             second = Integer.parseInt(m.group(4));
428         } else {
429             second = 0;
430         }
431         if (m.group(6) != null) {
432             String apm = m.group(6).toLowerCase();
433             if (apm.equals("pm")) {
434                 hour+=12;
435             }
436         }
437         if (DBG.isDebugEnabled()) {
438             DBG.debug("Setting hour: " + hour);
439             DBG.debug("Setting minute: " + minute);
440             DBG.debug("Setting second: " + second);
441         }
442         cal.set(Calendar.HOUR_OF_DAY, hour);
443         cal.set(Calendar.MINUTE, minute);
444         cal.set(Calendar.SECOND, second);
445         cal.set(Calendar.MILLISECOND, 0);
446         if (DBG.isDebugEnabled()) {
447             DBG.debug("Resulting cal: " + cal);
448         }
449     }
450     
451     /**
452      * Converts this AspDate object to a Calendar object 
453      * @return calendar object representing this AspDate object
454      */
455     public Calendar toCalendar()
456     {
457         return (Calendar)cal.clone();
458     }
459 
460     /**
461      * Converts this AspDate object to a Date object 
462      * @return date object representing this AspDate object
463      */
464     public Date toDate()
465     {
466         return cal.getTime();
467     }
468 
469     /**
470      * Get the month value of this AspDate
471      * @return month value
472      */
473     public int getMonth()
474     {
475         return cal.get(Calendar.MONTH);
476     }
477 
478     /**
479      * Get the day value of this AspDate
480      * @return day value
481      */
482     public int getDay()
483     {
484         return cal.get(Calendar.DAY_OF_MONTH);
485     }
486 
487     /**
488      * Get the year value of this AspDate
489      * @return year value
490      */
491     public int getYear()
492     {
493         return cal.get(Calendar.YEAR);
494     }
495 
496     /**
497      * Get the hour value of this AspDate
498      * @return hour value
499      */
500     public int getHour()
501     {
502         return cal.get(Calendar.HOUR_OF_DAY);
503     }
504 
505     /**
506      * Get the minute value of this AspDate
507      * @return minute value
508      */
509     public int getMinute()
510     {
511         return cal.get(Calendar.MINUTE);
512     }
513 
514     /**
515      * Get the second value of this AspDate
516      * @return second value
517      */
518     public int getSecond()
519     {
520         return cal.get(Calendar.SECOND);
521     }
522 
523     /**
524      * Does this object have a time value?
525      * @return true if this object has a time value, false otherwise.
526      */
527     public boolean hasTime()
528     {
529         return hasTime;
530     }
531 
532     /**
533      * Does this object have a date value?
534      * @return true if this object has a date value, false otherwise.
535      */
536     public boolean hasDate()
537     {
538         return hasDate;
539     }
540 
541     /**
542      * Convert this date to a string.
543      * @return String representation of this date.
544      */
545     public String toString()
546     {
547         if (!hasTime)
548         {
549             return shortDateFormat.format(toDate());
550         } else if (!hasDate) {
551             return longTimeFormat.format(toDate());
552         } else {
553             return longDateTimeFormat.format(toDate());
554         }
555     }
556 }