KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > es > NativeDate


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  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.es;
30
31 import com.caucho.util.Alarm;
32 import com.caucho.util.QDate;
33
34 /**
35  * JavaScript Date object
36  */

37 class NativeDate extends Native {
38   static final int NEW = 2;
39   static final int UTC = 3;
40   static final int VALUE_OF = 4;
41   static final int TO_STRING = 6;
42   static final int TO_UTC_STRING = 7;
43   static final int TO_ISO_STRING = 8;
44   static final int TO_UTC_ISO_STRING = 9;
45   static final int TO_ISO_DATE = 10;
46   static final int TO_UTC_ISO_DATE = 11;
47   static final int TO_LOCALE_STRING = 12;
48   static final int UTC_FORMAT = 13;
49   static final int FORMAT = 14;
50   static final int PARSE_DATE = 15;
51
52   static final int GET_FULL_YEAR = 20;
53   static final int GET_UTC_FULL_YEAR = 21;
54   static final int GET_MONTH = 22;
55   static final int GET_UTC_MONTH = 23;
56   static final int GET_DATE = 24;
57   static final int GET_UTC_DATE = 25;
58   static final int GET_DAY = 26;
59   static final int GET_UTC_DAY = 27;
60   static final int GET_HOURS = 28;
61   static final int GET_UTC_HOURS = 29;
62   static final int GET_MINUTES = 30;
63   static final int GET_UTC_MINUTES = 31;
64   static final int GET_SECONDS = 32;
65   static final int GET_UTC_SECONDS = 33;
66   static final int GET_MILLISECONDS = 34;
67   static final int GET_UTC_MILLISECONDS = 35;
68
69   static final int GET_TIMEZONE_OFFSET = 36;
70
71   static final int SET_FULL_YEAR = 50;
72   static final int SET_UTC_FULL_YEAR = 51;
73   static final int SET_MONTH = 52;
74   static final int SET_UTC_MONTH = 53;
75   static final int SET_DATE = 54;
76   static final int SET_UTC_DATE = 55;
77   static final int SET_HOURS = 56;
78   static final int SET_UTC_HOURS = 57;
79   static final int SET_MINUTES = 58;
80   static final int SET_UTC_MINUTES = 59;
81   static final int SET_SECONDS = 60;
82   static final int SET_UTC_SECONDS = 61;
83   static final int SET_MILLISECONDS = 62;
84   static final int SET_UTC_MILLISECONDS = 63;
85
86   static final int GET_MONTH_NAME = SET_UTC_MILLISECONDS + 1;
87   static final int GET_UTC_MONTH_NAME = GET_MONTH_NAME + 1;
88
89   private static String JavaDoc []monthNames = new String JavaDoc[] {
90     "January", "February", "March", "April", "May", "June",
91       "July", "August", "September", "October", "November", "December"
92       };
93
94   QDate localCal = QDate.createLocal();
95   QDate utcCal = new QDate();
96   QDate cal = localCal;
97
98   /**
99    * Create a new object based on a prototype
100    */

101   private NativeDate(String JavaDoc name, int n, int len)
102   {
103     super(name, len);
104
105     this.n = n;
106     // this.cal = cal;
107
}
108
109   /**
110    * Creates the native Object object
111    */

112   static ESObject create(Global resin)
113   {
114     // QDate cal = QDate.createLocal();
115

116     NativeDate nativeDate = new NativeDate("Date", NEW, 7);
117     ESObject dateProto = new ESDate(Long.MAX_VALUE, resin.objProto);
118     NativeWrapper date = new NativeWrapper(resin, nativeDate,
119                        dateProto, ESThunk.DATE_THUNK);
120     nativeDate.newN = nativeDate.n;
121     resin.dateProto = dateProto;
122
123     put(dateProto, "toString", TO_STRING, 0);
124     put(dateProto, "getTime", VALUE_OF, 0);
125     put(dateProto, "valueOf", VALUE_OF, 0);
126     put(dateProto, "toUTCString", TO_UTC_STRING, 0);
127     put(dateProto, "toGMTString", TO_UTC_STRING, 0);
128     put(dateProto, "toLocalISO8601", TO_ISO_STRING, 0);
129     put(dateProto, "toISO8601", TO_UTC_ISO_STRING, 0);
130     put(dateProto, "format", FORMAT, 0);
131     put(dateProto, "UTCFormat", UTC_FORMAT, 0);
132
133     put(dateProto, "toLocaleString", TO_LOCALE_STRING, 0);
134     put(dateProto, "getUTCYear", GET_UTC_FULL_YEAR, 0);
135     put(dateProto, "getUTCFullYear", GET_UTC_FULL_YEAR, 0);
136     put(dateProto, "getUTCMonth", GET_UTC_MONTH, 0);
137     put(dateProto, "getUTCDate", GET_UTC_DATE, 0);
138     put(dateProto, "getUTCDay", GET_UTC_DAY, 0);
139     put(dateProto, "getUTCHours", GET_UTC_HOURS, 0);
140     put(dateProto, "getUTCMinutes", GET_UTC_MINUTES, 0);
141     put(dateProto, "getUTCSeconds", GET_UTC_SECONDS, 0);
142     put(dateProto, "getUTCMilliseconds", GET_UTC_MILLISECONDS, 0);
143
144     put(dateProto, "setUTCYear", SET_UTC_FULL_YEAR, 1);
145     put(dateProto, "setUTCFullYear", SET_UTC_FULL_YEAR, 1);
146     put(dateProto, "setUTCMonth", SET_UTC_MONTH, 2);
147     put(dateProto, "setUTCDate", SET_UTC_DATE, 3);
148     put(dateProto, "setUTCHours", SET_UTC_HOURS, 4);
149     put(dateProto, "setUTCMinutes", SET_UTC_MINUTES, 3);
150     put(dateProto, "setUTCSeconds", SET_UTC_SECONDS, 2);
151     put(dateProto, "setUTCMilliseconds", SET_UTC_MILLISECONDS, 1);
152
153     put(dateProto, "getYear", GET_FULL_YEAR, 0);
154     put(dateProto, "getFullYear", GET_FULL_YEAR, 0);
155     put(dateProto, "getMonth", GET_MONTH, 0);
156     put(dateProto, "getMonthName", GET_MONTH_NAME, 0);
157     put(dateProto, "getDate", GET_DATE, 0);
158     put(dateProto, "getDay", GET_DAY, 0);
159     put(dateProto, "getHours", GET_HOURS, 0);
160     put(dateProto, "getMinutes", GET_MINUTES, 0);
161     put(dateProto, "getSeconds", GET_SECONDS, 0);
162     put(dateProto, "getMilliseconds", GET_MILLISECONDS, 0);
163
164     put(dateProto, "getTimezoneOffset", GET_TIMEZONE_OFFSET, 0);
165     put(dateProto, "setYear", SET_FULL_YEAR, 3);
166     put(dateProto, "setFullYear", SET_FULL_YEAR, 3);
167     put(dateProto, "setMonth", SET_MONTH, 2);
168     put(dateProto, "setDate", SET_DATE, 1);
169     put(dateProto, "setHours", SET_HOURS, 4);
170     put(dateProto, "setMinutes", SET_MINUTES, 3);
171     put(dateProto, "setSeconds", SET_SECONDS, 2);
172     put(dateProto, "setMilliseconds", SET_MILLISECONDS, 1);
173
174     put(date, "UTC", UTC, 7);
175     put(date, "parse", PARSE_DATE, 1);
176
177     dateProto.setClean();
178     date.setClean();
179
180     return date;
181   }
182
183   private static void put(ESObject obj, String JavaDoc name, int n, int len)
184   {
185     obj.put(ESId.intern(name), new NativeDate(name, n, len), DONT_ENUM);
186   }
187
188   public ESBase call(Call eval, int length) throws Throwable JavaDoc
189   {
190     long time = 0;
191     double value;
192     ESBase error;
193
194     synchronized (cal) {
195
196     int off = 0;
197     switch (n) {
198     case NEW:
199       return ESDate.create(create(eval, length, n));
200
201     case UTC:
202       return ESNumber.create(create(eval, length, n));
203
204     case TO_STRING:
205     case TO_UTC_STRING:
206       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
207     return error;
208
209       return ESString.create(cal.printDate());
210
211     case TO_ISO_STRING:
212     case TO_UTC_ISO_STRING:
213       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
214     return error;
215
216       return ESString.create(cal.printISO8601());
217
218     case TO_ISO_DATE:
219     case TO_UTC_ISO_DATE:
220       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
221     return error;
222
223       return ESString.create(cal.printISO8601Date());
224
225     case FORMAT:
226     case UTC_FORMAT:
227       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
228     return error;
229
230       return ESString.create(cal.format(eval.getArgString(0, length)));
231
232     case TO_LOCALE_STRING:
233       if ((error = calculate(eval.getArg(-1), 1, TO_STRING)) != null)
234     return error;
235
236       return ESString.create(cal.printLocaleDate());
237
238     case VALUE_OF:
239       if (! (eval.getArg(-1) instanceof ESDate))
240     throw new ESException("valueOf must be bound to date");
241       
242       value = (double) ((ESDate) eval.getArg(-1)).time;
243       if (value > 8.64e15 || value < -8.64e15 || Double.isNaN(value))
244     value = 0.0/0.0;
245
246       return ESNumber.create(value);
247
248     case PARSE_DATE:
249       if (length < 0)
250     return ESNumber.NaN;
251
252       try {
253     long lvalue = cal.parseDate(eval.getArg(0).toStr().toString());
254     return ESNumber.create(millisToDouble(lvalue));
255       } catch (Exception JavaDoc e) {
256     throw new ESException(e.toString());
257       }
258
259
260     case GET_FULL_YEAR:
261     case GET_UTC_FULL_YEAR:
262       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
263     return error;
264
265       return ESNumber.create((double) cal.get(cal.YEAR));
266
267     case GET_MONTH:
268     case GET_UTC_MONTH:
269       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
270     return error;
271
272       return ESNumber.create((double) cal.get(cal.MONTH));
273
274     case GET_MONTH_NAME:
275     case GET_UTC_MONTH_NAME:
276     {
277     if ((error = calculate(eval.getArg(-1), 1, n)) != null)
278       return error;
279
280     int month = (int) cal.get(cal.MONTH);
281
282     return ESString.create(monthNames[month]);
283     }
284
285     case GET_DATE:
286     case GET_UTC_DATE:
287       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
288     return error;
289
290       return ESNumber.create((double) cal.get(cal.DAY_OF_MONTH) + 1);
291
292     case GET_DAY:
293     case GET_UTC_DAY:
294       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
295     return error;
296
297       return ESNumber.create((double) cal.get(cal.DAY));
298
299     case GET_HOURS:
300     case GET_UTC_HOURS:
301       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
302     return error;
303
304       return ESNumber.create((double) (cal.get(cal.HOUR)));
305
306     case GET_MINUTES:
307     case GET_UTC_MINUTES:
308       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
309     return error;
310
311       return ESNumber.create((double) (cal.get(cal.MINUTE)));
312
313     case GET_SECONDS:
314     case GET_UTC_SECONDS:
315       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
316     return error;
317
318       return ESNumber.create((double) (cal.get(cal.SECOND)));
319
320     case GET_MILLISECONDS:
321     case GET_UTC_MILLISECONDS:
322       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
323     return error;
324
325       return ESNumber.create((double) cal.get(cal.MILLISECOND));
326
327     case GET_TIMEZONE_OFFSET:
328       if ((error = calculate(eval.getArg(-1), 1, n)) != null)
329     return error;
330
331       return ESNumber.create((double) (cal.getZoneOffset() / 60000));
332
333     case SET_DATE:
334     case SET_UTC_DATE:
335       off--;
336
337     case SET_MONTH:
338     case SET_UTC_MONTH:
339       off--;
340
341     case SET_FULL_YEAR:
342     case SET_UTC_FULL_YEAR:
343       if ((error = calculate(eval.getArg(-1), length, n)) != null)
344     return error;
345
346       if (0 <= off)
347     cal.set(cal.YEAR, (long) eval.getArg(off).toNum());
348
349       if (0 <= off + 1 && off + 1 < length) {
350     value = eval.getArg(off + 1).toNum();
351     cal.set(cal.MONTH,
352         (long) (Double.isNaN(value) ? Long.MAX_VALUE : value));
353       }
354       if (0 <= off + 2 && off + 2 < length) {
355     value = eval.getArg(off + 2).toNum();
356     cal.set(cal.DAY_OF_MONTH,
357         (long) (Double.isNaN(value) ? Long.MAX_VALUE : value - 1));
358       }
359
360       return create(eval.getArg(-1), n);
361
362     case SET_MILLISECONDS:
363     case SET_UTC_MILLISECONDS:
364       off--;
365
366     case SET_SECONDS:
367     case SET_UTC_SECONDS:
368       off--;
369
370     case SET_MINUTES:
371     case SET_UTC_MINUTES:
372       off--;
373
374     case SET_HOURS:
375     case SET_UTC_HOURS:
376       if ((error = calculate(eval.getArg(-1), length, n)) != null)
377     return error;
378
379       if (0 <= off) {
380     value = eval.getArg(off).toNum();
381     cal.set(cal.HOUR,
382         (long) (Double.isNaN(value) ? Long.MAX_VALUE : value));
383       }
384
385       if (0 <= off + 1 && off + 1 < length) {
386     value = eval.getArg(off + 1).toNum();
387     cal.set(cal.MINUTE,
388         (long) (Double.isNaN(value) ? Long.MAX_VALUE : value));
389       }
390       if (0 <= off + 2 && off + 2 < length) {
391     value = eval.getArg(off + 2).toNum();
392     cal.set(cal.SECOND,
393         (long) (Double.isNaN(value) ? Long.MAX_VALUE : value));
394       }
395       if (0 <= off + 3 && off + 3 < length) {
396     value = eval.getArg(off + 3).toNum();
397     cal.set(cal.MILLISECOND,
398         (long) (Double.isNaN(value) ? Long.MAX_VALUE : value));
399       }
400
401       return create(eval.getArg(-1), n);
402
403     default:
404       throw new ESException("Unknown object function");
405     }
406     }
407   }
408
409   public ESBase construct(Call eval, int length) throws Throwable JavaDoc
410   {
411     if (cal == null)
412       cal = new QDate();
413
414     if (n != NEW)
415       return super.construct(eval, length);
416     
417     synchronized (cal) {
418       return ESDate.create(create(eval, length, NEW));
419     }
420   }
421
422   private long create(Call eval, int length, int code)
423     throws Throwable JavaDoc
424   {
425     boolean isLocal = (code & 1) == 0;
426     long value = 0;
427
428     if (length == 0) {
429       return Alarm.getCurrentTime();
430     }
431     else if (length == 1)
432       value = (long) (eval.getArg(0).toNum());
433     else if (length >= 3) {
434       long year = (long) eval.getArg(0).toNum();
435       long month = (long) eval.getArg(1).toNum();
436       long day = (long) eval.getArg(2).toNum() - 1;
437       
438       long hour = 0;
439       if (length >= 4)
440     hour = (long) eval.getArg(3).toNum();
441
442       long minute = 0;
443       if (length >= 5)
444     minute = (long) eval.getArg(4).toNum();
445
446       long second = 0;
447       if (length >= 6)
448     second = (long) eval.getArg(5).toNum();
449
450       long ms = 0;
451       if (length >= 7)
452     ms = (long) eval.getArg(6).toNum();
453
454       cal.setDate(year, month, day);
455       cal.setTime(hour, minute, second, ms);
456
457       value = cal.get(cal.TIME);
458
459       if (isLocal)
460     value -= cal.getZoneOffset();
461     }
462     else
463       value = Long.MIN_VALUE;
464
465     return value;
466   }
467
468   private double millisToDouble(long millis)
469   {
470     double dvalue = millis;
471     if (dvalue > 8.64e15 || dvalue < -8.64e15 || Double.isNaN(dvalue))
472       dvalue = 0.0/0.0;
473
474     return dvalue;
475   }
476
477   private ESBase create(ESBase obj, int code) throws ESException
478   {
479     boolean isLocal = (code & 1) == 0;
480
481     long value = cal.get(cal.TIME);
482
483     if (isLocal)
484       value -= cal.getZoneOffset();
485
486     double dvalue = value;
487     if (dvalue > 8.64e15 || dvalue < -8.64e15 || Double.isNaN(dvalue))
488       dvalue = 0.0/0.0;
489
490     if (! (obj instanceof ESDate))
491       return ESNumber.create(dvalue);
492
493     ESNumber newValue = ESNumber.create(dvalue);
494     ((ESDate) obj).time = (long) dvalue;
495
496     return newValue;
497   }
498
499   private ESBase calculate(ESBase arg, int length, int code)
500     throws Throwable JavaDoc
501   {
502     boolean isLocal = (code & 1) == 0;
503
504     double value = arg.toNum();
505     if (Double.isNaN(value) || value > 8.64e15 || value < -8.64e15 ||
506     length < 1)
507       return ESNumber.NaN;
508
509     long time = (long) value;
510
511     if (isLocal)
512       cal = localCal;
513     else
514       cal = utcCal;
515
516     cal.setGMTTime(time);
517
518     return null;
519   }
520 }
521
Popular Tags