001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010: package org.mmbase.util;
011:
012: import org.mmbase.util.dateparser.*;
013: import java.util.*;
014:
015: /**
016: * A DynamicDate is a Date object that has no fixed value, like 'now'. It is unmodifiable, so all
017: * set-methods throw exceptions. There is no public constructor, but a public static {@link #getInstance}.
018: *
019: * Sadly, the Date object of Sun is implemented using private static methods which use private
020: * fields, of the Date object so not everything could be overridden perfectly. So, if e.g. a dynamic
021: * date could be an argument of a 'after' or 'before' method, it is better to wrap it with {@link
022: * DynamicDate#eval} first.
023: *
024: * @author Michiel Meeuwissen
025: * @since MMBase-1.8
026: */
027: public class DynamicDate extends Date {
028:
029: /**
030: * Parses a format string and returns Date instance, possibly a 'dynamic one'. Not necessary a new one, which
031: * does not matter, because these objects are unmodifiable anyway.
032: *
033: * If the request date is not dynamic, but absolutely defined, a normal Date object is returned.
034: */
035: public static Date getInstance(final String format)
036: throws ParseException {
037: if (format.equals("null"))
038: return null;
039: DateParser parser = new DateParser(new java.io.StringReader(
040: format));
041: try {
042: parser.start();
043: if (parser.dynamic()) {
044: return new DynamicDate(format);
045: } else {
046: return parser.toDate();
047: }
048: } catch (ParseException pe) {
049: ParseException p = new ParseException("In " + format + " "
050: + pe.getMessage());
051: p.initCause(pe);
052: throw p;
053: }
054:
055: }
056:
057: /**
058: * Makes sure the argument 'date' is no DynamicDate any more. So this returns a fixed date
059: * object when the argument is a DynamicDate and simply the argument if it is not.
060: */
061: public static Date eval(final Date date) {
062: if (date instanceof DynamicDate) {
063: return ((DynamicDate) date).evalDate();
064: } else {
065: return date;
066: }
067: }
068:
069: /**
070: * The original string by which this instance was gotten.
071: */
072: protected final String date;
073:
074: protected DynamicDate(String d) {
075: date = d;
076: }
077:
078: public String getFormat() {
079: return date;
080: }
081:
082: /**
083: * This produces a normal Date object, and is called everytime when that is needed. Users can call it too, if they want to fixated
084: */
085: protected Date evalDate() {
086: DateParser parser = new DateParser(new java.io.StringReader(
087: date));
088: try {
089: parser.start();
090: return parser.toDate();
091: } catch (org.mmbase.util.dateparser.ParseException pe) {
092: return new Date();
093: }
094: }
095:
096: // all methods of Date itself are simply wrapped..
097:
098: public boolean after(Date when) {
099: return evalDate().after(when);
100: }
101:
102: public boolean before(Date when) {
103: return evalDate().before(when);
104: }
105:
106: public Object clone() {
107: try {
108: return getInstance(date);
109: } catch (org.mmbase.util.dateparser.ParseException pe) {
110: return new Date();
111: }
112: }
113:
114: public int compareTo(Date anotherDate) {
115: return evalDate().compareTo(anotherDate);
116: }
117:
118: public boolean equals(Object obj) {
119: if (obj instanceof DynamicDate) {
120: return date.equals(((DynamicDate) obj).date);
121: } else {
122: return false;
123: }
124: }
125:
126: public int getDate() {
127: return evalDate().getDate();
128: }
129:
130: public int getDay() {
131: return evalDate().getDay();
132: }
133:
134: public int getHours() {
135: return evalDate().getHours();
136: }
137:
138: public int getMinutes() {
139: return evalDate().getMinutes();
140: }
141:
142: public int getMonth() {
143: return evalDate().getMonth();
144: }
145:
146: public int getSeconds() {
147: return evalDate().getSeconds();
148: }
149:
150: public long getTime() {
151: return evalDate().getTime();
152: }
153:
154: public int getTimezoneOffset() {
155: return evalDate().getTimezoneOffset();
156: }
157:
158: public int getYear() {
159: return evalDate().getYear();
160: }
161:
162: public int hashCode() {
163: return date.hashCode();
164: }
165:
166: public void setDate(int date) {
167: throw new UnsupportedOperationException(
168: "Cannot set date in dynamic date");
169: }
170:
171: public void setHours(int hours) {
172: throw new UnsupportedOperationException(
173: "Cannot set date in dynamic date");
174: }
175:
176: public void setMinutes(int minutes) {
177: throw new UnsupportedOperationException(
178: "Cannot set date in dynamic date");
179: }
180:
181: public void setMonth(int month) {
182: throw new UnsupportedOperationException(
183: "Cannot set date in dynamic date");
184: }
185:
186: public void setSeconds(int seconds) {
187: throw new UnsupportedOperationException(
188: "Cannot set date in dynamic date");
189: }
190:
191: public void setTime(long time) {
192: throw new UnsupportedOperationException(
193: "Cannot set date in dynamic date");
194: }
195:
196: public void setYear(int year) {
197: throw new UnsupportedOperationException(
198: "Cannot set date in dynamic date");
199: }
200:
201: public String toGMTString() {
202: return evalDate().toGMTString();
203: }
204:
205: public String toLocaleString() {
206: return evalDate().toLocaleString();
207: }
208:
209: public String toString() {
210: return date + ": " + evalDate().toString();
211: }
212:
213: public static String[] getDemo() {
214: return new String[] {
215: "0",
216: "10000",
217: "-10000",
218: "+1000", // just numbers a bit after 1970, a bit before
219: "1973-05-03",
220: "2006-05-09",
221: "-3-12-25", // absolute dates
222: "2000-01-01 16:00", "TZUTC 2001-01-01 16:00",
223: "today 12:34:56.789", "now", "today", "tomorrow",
224: "now + 10 minute", "today + 5 day", "now this year",
225: "next august", "today + 6 month next august",
226: "tomonth", "borreltijd", "today + 5 dayish",
227: "yesteryear", "mondayish", "duration + 5 minute",
228: "duration + 100 year", "TZUTC today noon",
229: "TZEurope/Amsterdam today noon", "TZUTC today",
230: "TZEurope/Amsterdam today", "TZ UTC today noon",
231: "TZ Europe/Amsterdam today noon", "TZ UTC today",
232: "TZ Europe/Amsterdam today",
233: "TZ Europe/Amsterdam -1000", "today 6 oclock",
234: "today 23 oclock", "today 43 oclock", "tosecond",
235: "tominute", "tohour", "today", "previous monday",
236: "tomonth", "toyear", "tocentury", "tocentury_pedantic",
237: "toera", "now this second", "now this minute",
238: "now this hour", "now this day",
239: "today previous monday", "now this month",
240: "now this year", "now this century", "now this era",
241: "now - 15 year this century",
242: "now - 20 year this century_pedantic",
243: "today + 2 century", "toera - 1 minute", "this july",
244: "previous july", "next july", "this sunday",
245: "previous sunday", "next sunday", "2009-W01-01",
246: "2009-W53-7", "2006-123", "2005-01-01 this monday" };
247: }
248:
249: public static void main(String argv[])
250: throws java.text.ParseException, ParseException {
251:
252: //System.out.println("" + Arrays.asList(TimeZone.getAvailableIDs()));
253: //System.out.println(TimeZone.getDefault());
254: java.text.DateFormat formatter = new java.text.SimpleDateFormat(
255: "GGGG yyyy-MM-dd HH:mm:ss.SSS zzz E");
256: if (argv.length == 0) {
257: String[] demo = getDemo();
258: for (String element : demo) {
259: try {
260: Date d1 = getInstance(element);
261: System.out.print(formatter.format(d1) + "\t");
262: } catch (Exception e) {
263: System.out.println(e.getMessage());
264: }
265: System.out.println(element);
266:
267: }
268: System.out
269: .println("This was demo, you can also call with an argument, to try it yourself");
270: System.out
271: .println("Also try with different values for -Duser.timezone=");
272: } else {
273: Date d1 = getInstance(argv[0]);
274: //Date d2 = Casting.ISO_8601_UTC.parse(argv[0]);
275: //Date d3 = new Date(Long.MIN_VALUE);
276: System.out.println(formatter.format(d1) + " "
277: + d1.getTime());
278: //System.out.println("" + d2 + " " + d2.getTime());
279: //System.out.println("" + d3 + " " + d3.getTime());
280: }
281: }
282:
283: }
|