1 28 29 package com.caucho.es; 30 31 import com.caucho.util.Alarm; 32 import com.caucho.util.QDate; 33 34 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 []monthNames = new String [] { 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 101 private NativeDate(String name, int n, int len) 102 { 103 super(name, len); 104 105 this.n = n; 106 } 108 109 112 static ESObject create(Global resin) 113 { 114 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 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 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 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 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 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 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 |