001 // TODO Time constructor muss auch noch entfernt werden und durch DateUtil methode ersetzen 002 package railo.runtime.op.date; 003 004 import java.text.DateFormat; 005 import java.text.ParsePosition; 006 import java.util.Calendar; 007 import java.util.Date; 008 import java.util.Locale; 009 import java.util.TimeZone; 010 011 import railo.commons.date.DateTimeUtil; 012 import railo.commons.date.JREDateTimeUtil; 013 import railo.commons.date.TimeZoneConstants; 014 import railo.commons.i18n.FormatUtil; 015 import railo.commons.lang.StringUtil; 016 import railo.runtime.Component; 017 import railo.runtime.engine.ThreadLocalPageContext; 018 import railo.runtime.exp.ExpressionException; 019 import railo.runtime.exp.PageException; 020 import railo.runtime.op.Castable; 021 import railo.runtime.op.Caster; 022 import railo.runtime.op.Decision; 023 import railo.runtime.type.ObjectWrap; 024 import railo.runtime.type.dt.DateTime; 025 import railo.runtime.type.dt.DateTimeImpl; 026 import railo.runtime.type.dt.Time; 027 import railo.runtime.type.dt.TimeImpl; 028 029 /** 030 * Class to cast Strings to Date Objects 031 */ 032 public final class DateCaster { 033 034 private static final Object NULL = new Object(); 035 036 //private static short MODE_DAY_STR=1; 037 //private static short MODE_MONTH_STR=2; 038 //private static short MODE_NONE=4; 039 private static long DEFAULT_VALUE=Long.MIN_VALUE; 040 041 private static DateTimeUtil util=DateTimeUtil.getInstance(); 042 public static boolean classicStyle=false; 043 044 /** 045 * converts a Object to a DateTime Object (Advanced but slower) 046 * @param o Object to Convert 047 * @param timezone 048 * @return Date Time Object 049 * @throws PageException 050 */ 051 public static DateTime toDateAdvanced(Object o,TimeZone timezone) throws PageException { 052 if(o instanceof Date) { 053 if(o instanceof DateTime) return (DateTime)o; 054 return new DateTimeImpl((Date)o); 055 } 056 else if(o instanceof Castable) return ((Castable)o).castToDateTime(); 057 else if(o instanceof String) { 058 DateTime dt=toDateAdvanced((String)o,timezone,null); 059 if(dt==null) 060 throw new ExpressionException("can't cast ["+o+"] to date value"); 061 return dt; 062 } 063 else if(o instanceof Number) return util.toDateTime(((Number)o).doubleValue()); 064 else if(o instanceof ObjectWrap) return toDateAdvanced(((ObjectWrap)o).getEmbededObject(),timezone); 065 else if(o instanceof Calendar){ 066 067 return new DateTimeImpl((Calendar)o); 068 } 069 throw new ExpressionException("can't cast ["+Caster.toClassName(o)+"] to date value"); 070 } 071 072 /** 073 * converts a Object to a DateTime Object (Advanced but slower) 074 * @param str String to Convert 075 * @param timezone 076 * @return Date Time Object 077 * @throws PageException 078 */ 079 public static DateTime toDateAdvanced(String str,TimeZone timezone) throws PageException { 080 DateTime dt=toDateAdvanced(str,timezone,null); 081 if(dt==null) 082 throw new ExpressionException("can't cast ["+str+"] to date value"); 083 return dt; 084 } 085 086 /** 087 * converts a Object to a DateTime Object (Advanced but slower), returns null if invalid string 088 * @param o Object to Convert 089 * @param timeZone 090 * @param defaultValue 091 * @return Date Time Object 092 */ 093 public static DateTime toDateAdvanced(Object o,TimeZone timeZone, DateTime defaultValue) { 094 if(o instanceof DateTime) return (DateTime)o; 095 else if(o instanceof Date) return new DateTimeImpl((Date)o); 096 else if(o instanceof Castable) { 097 return ((Castable)o).castToDateTime(defaultValue); 098 } 099 else if(o instanceof String) return toDateAdvanced(o.toString(),timeZone,defaultValue); 100 else if(o instanceof Number) return util.toDateTime(((Number)o).doubleValue()); 101 else if(o instanceof Calendar){ 102 return new DateTimeImpl((Calendar)o); 103 } 104 else if(o instanceof ObjectWrap) return toDateAdvanced(((ObjectWrap)o).getEmbededObject(defaultValue),timeZone,defaultValue); 105 return defaultValue; 106 } 107 108 /** 109 * converts a String to a DateTime Object (Advanced but slower), returns null if invalid string 110 * @param str String to convert 111 * @param timeZone 112 * @param defaultValue 113 * @return Date Time Object 114 */ 115 public static DateTime toDateAdvanced(String str,boolean alsoNumbers,TimeZone timeZone, DateTime defaultValue) { 116 str=str.trim(); 117 if(StringUtil.isEmpty(str)) return defaultValue; 118 timeZone=ThreadLocalPageContext.getTimeZone(timeZone); 119 DateTime dt=toDateSimple(str,alsoNumbers,true,timeZone,defaultValue); 120 if(dt==null) { 121 DateFormat[] formats = FormatUtil.getCFMLFormats(timeZone, true); 122 synchronized(formats){ 123 Date d; 124 ParsePosition pp=new ParsePosition(0); 125 for(int i=0;i<formats.length;i++) { 126 //try { 127 pp.setErrorIndex(-1); 128 pp.setIndex(0); 129 d = formats[i].parse(str,pp); 130 if (pp.getIndex() == 0 || d==null || pp.getIndex()<str.length()) continue; 131 dt= new DateTimeImpl(d.getTime(),false); 132 return dt; 133 //}catch (ParseException e) {} 134 } 135 } 136 dt=toDateTime(Locale.US, str, timeZone,defaultValue, false); 137 } 138 return dt; 139 } 140 141 142 143 /** 144 * parse a string to a Datetime Object 145 * @param locale 146 * @param str String representation of a locale Date 147 * @param tz 148 * @return DateTime Object 149 * @throws PageException 150 */ 151 public static DateTime toDateTime(Locale locale,String str, TimeZone tz,boolean useCommomDateParserAsWell) throws PageException { 152 153 DateTime dt=toDateTime(locale, str, tz,null,useCommomDateParserAsWell); 154 if(dt==null){ 155 /* FUTURE 4.1 156 String prefix=locale.getLanguage()+"-"+locale.getCountry()+"-"; 157 throw new ExpressionException("can't cast ["+str+"] to date value", 158 "to add custom formats for "+LocaleFactory.toString(locale)+ 159 ", create/extend on of the following files ["+prefix+"datetime.df (for date time formats), "+prefix+"date.df (for date formats) or "+prefix+"time.df (for time formats)] in the following directory [<context>/railo/locales]."+ 160 ""); 161 */ 162 throw new ExpressionException("can't cast ["+str+"] to date value"); 163 } 164 return dt; 165 } 166 167 /** 168 * parse a string to a Datetime Object, returns null if can't convert 169 * @param locale 170 * @param str String representation of a locale Date 171 * @param tz 172 * @param defaultValue 173 * @return datetime object 174 */ 175 public synchronized static DateTime toDateTime(Locale locale,String str, TimeZone tz, DateTime defaultValue,boolean useCommomDateParserAsWell) { 176 str=str.trim(); 177 tz=ThreadLocalPageContext.getTimeZone(tz); 178 DateFormat[] df; 179 180 // get Calendar 181 Calendar c=JREDateTimeUtil.getCalendar(locale); 182 //synchronized(c){ 183 184 // datetime 185 ParsePosition pp=new ParsePosition(0); 186 df=FormatUtil.getDateTimeFormats(locale,tz,false);//dfc[FORMATS_DATE_TIME]; 187 Date d; 188 //print.e(locale.getDisplayName(Locale.ENGLISH)); 189 for(int i=0;i<df.length;i++) { 190 //print.e(df[i].format(new Date())); 191 pp.setErrorIndex(-1); 192 pp.setIndex(0); 193 //try { 194 df[i].setTimeZone(tz); 195 d = df[i].parse(str,pp); 196 if (pp.getIndex() == 0 || d==null || pp.getIndex()<str.length()) continue; 197 198 synchronized(c) { 199 optimzeDate(c,tz,d); 200 return new DateTimeImpl(c.getTime()); 201 } 202 //}catch (ParseException e) {} 203 } 204 // date 205 df=FormatUtil.getDateFormats(locale,tz,false);//dfc[FORMATS_DATE]; 206 //print.e(locale.getDisplayName(Locale.ENGLISH)); 207 for(int i=0;i<df.length;i++) { 208 //print.e(df[i].format(new Date())); 209 pp.setErrorIndex(-1); 210 pp.setIndex(0); 211 //try { 212 df[i].setTimeZone(tz); 213 d=df[i].parse(str,pp); 214 if (pp.getIndex() == 0 || d==null || pp.getIndex()<str.length()) continue; 215 216 synchronized(c) { 217 optimzeDate(c,tz,d); 218 return new DateTimeImpl(c.getTime()); 219 } 220 //}catch (ParseException e) {} 221 } 222 223 // time 224 df=FormatUtil.getTimeFormats(locale,tz,false);//dfc[FORMATS_TIME]; 225 //print.e(locale.getDisplayName(Locale.ENGLISH)); 226 for(int i=0;i<df.length;i++) { 227 //print.e(df[i].format(new Date())); 228 pp.setErrorIndex(-1); 229 pp.setIndex(0); 230 //try { 231 df[i].setTimeZone(tz); 232 d=df[i].parse(str,pp); 233 if (pp.getIndex() == 0 || d==null || pp.getIndex()<str.length()) continue; 234 synchronized(c) { 235 c.setTimeZone(tz); 236 c.setTime(d); 237 c.set(Calendar.YEAR,1899); 238 c.set(Calendar.MONTH,11); 239 c.set(Calendar.DAY_OF_MONTH,30); 240 c.setTimeZone(tz); 241 } 242 return new DateTimeImpl(c.getTime()); 243 //}catch (ParseException e) {} 244 } 245 //} 246 if(useCommomDateParserAsWell)return DateCaster.toDateSimple(str, false,true, tz, defaultValue); 247 return defaultValue; 248 } 249 250 private static void optimzeDate(Calendar c, TimeZone tz, Date d) { 251 c.setTimeZone(tz); 252 c.setTime(d); 253 int year=c.get(Calendar.YEAR); 254 if(year<40) c.set(Calendar.YEAR,2000+year); 255 else if(year<100) c.set(Calendar.YEAR,1900+year); 256 } 257 258 259 260 public static DateTime toDateAdvanced(String str, TimeZone timeZone, DateTime defaultValue) { 261 return toDateAdvanced(str, true, timeZone,defaultValue); 262 } 263 264 /** 265 * converts a boolean to a DateTime Object 266 * @param b boolean to Convert 267 * @param timeZone 268 * @return coverted Date Time Object 269 */ 270 public static DateTime toDateSimple(boolean b, TimeZone timeZone) { 271 return toDateSimple(b?1L:0L, timeZone); 272 } 273 274 /** 275 * converts a char to a DateTime Object 276 * @param c char to Convert 277 * @param timeZone 278 * @return coverted Date Time Object 279 */ 280 public static DateTime toDateSimple(char c, TimeZone timeZone) { 281 return toDateSimple((long)c, timeZone); 282 } 283 284 /** 285 * converts a double to a DateTime Object 286 * @param d double to Convert 287 * @param timeZone 288 * @return coverted Date Time Object 289 */ 290 public static DateTime toDateSimple(double d, TimeZone timeZone) { 291 return toDateSimple((long)d, timeZone); 292 } 293 294 /* * 295 * converts a double to a DateTime Object 296 * @param d double to Convert 297 * @param timeZone 298 * @return coverted Date Time Object 299 * / 300 public static DateTime toDateSimple(long l, TimeZone timezone) { 301 return new DateTimeImpl(l,false); 302 }*/ 303 304 /** 305 * converts a Object to a DateTime Object, returns null if invalid string 306 * @param o Object to Convert 307 * @param timeZone 308 * @return coverted Date Time Object 309 * @throws PageException 310 */ 311 public static DateTime toDateSimple(Object o, boolean alsoNumbers,boolean alsoMonthString, TimeZone timeZone) throws PageException { 312 if(o instanceof DateTime) return (DateTime)o; 313 else if(o instanceof Date) return new DateTimeImpl((Date)o); 314 else if(o instanceof Castable) return ((Castable)o).castToDateTime(); 315 else if(o instanceof String) return toDateSimple(o.toString(),alsoNumbers,alsoMonthString, timeZone); 316 else if(o instanceof Number) return util.toDateTime(((Number)o).doubleValue()); 317 else if(o instanceof Calendar) return new DateTimeImpl((Calendar)o); 318 else if(o instanceof ObjectWrap) return toDateSimple(((ObjectWrap)o).getEmbededObject(),alsoNumbers,alsoMonthString,timeZone); 319 else if(o instanceof Calendar){ 320 return new DateTimeImpl((Calendar)o); 321 } 322 323 if(o instanceof Component) 324 throw new ExpressionException("can't cast component ["+((Component)o).getAbsName()+"] to date value"); 325 326 throw new ExpressionException("can't cast ["+Caster.toTypeName(o)+"] to date value"); 327 } 328 329 public static DateTime toDateSimple(Object o, boolean alsoNumbers,boolean alsoMonthString, TimeZone timeZone, DateTime defaultValue) { 330 if(o instanceof DateTime) return (DateTime)o; 331 else if(o instanceof Date) return new DateTimeImpl((Date)o); 332 else if(o instanceof Castable) return ((Castable)o).castToDateTime(defaultValue); 333 else if(o instanceof String) return toDateSimple(o.toString(),alsoNumbers,alsoMonthString, timeZone,defaultValue); 334 else if(o instanceof Number) return util.toDateTime(((Number)o).doubleValue()); 335 else if(o instanceof Calendar) return new DateTimeImpl((Calendar)o); 336 else if(o instanceof ObjectWrap) { 337 Object eo = ((ObjectWrap)o).getEmbededObject(NULL); 338 if(eo==NULL) return defaultValue; 339 return toDateSimple(eo,alsoNumbers,alsoMonthString,timeZone,defaultValue); 340 } 341 else if(o instanceof Calendar){ 342 return new DateTimeImpl((Calendar)o); 343 } 344 return defaultValue; 345 } 346 347 /** 348 * converts a Object to a DateTime Object, returns null if invalid string 349 * @param str String to Convert 350 * @param timeZone 351 * @return coverted Date Time Object 352 * @throws PageException 353 */ 354 public static DateTime toDateSimple(String str, TimeZone timeZone) throws PageException { 355 DateTime dt=toDateSimple(str,true,true, timeZone,null); 356 if(dt==null) 357 throw new ExpressionException("can't cast ["+str+"] to date value"); 358 return dt; 359 } 360 361 /** 362 * converts a Object to a Time Object, returns null if invalid string 363 * @param o Object to Convert 364 * @return coverted Date Time Object 365 * @throws PageException 366 */ 367 public static Time toTime(TimeZone timeZone,Object o) throws PageException { 368 if(o instanceof Time) return (Time)o; 369 else if(o instanceof Date) return new TimeImpl((Date)o); 370 else if(o instanceof Castable) return new TimeImpl(((Castable)o).castToDateTime()); 371 else if(o instanceof String) { 372 Time dt=toTime(timeZone,o.toString(),null); 373 if(dt==null) 374 throw new ExpressionException("can't cast ["+o+"] to time value"); 375 return dt; 376 } 377 else if(o instanceof ObjectWrap) return toTime(timeZone,((ObjectWrap)o).getEmbededObject()); 378 else if(o instanceof Calendar){ 379 // TODO check timezone offset 380 return new TimeImpl(((Calendar)o).getTimeInMillis(),false); 381 } 382 throw new ExpressionException("can't cast ["+Caster.toClassName(o)+"] to time value"); 383 } 384 385 public static DateTime toDateAdvanced(Object o,boolean alsoNumbers, TimeZone timeZone, DateTime defaultValue) { 386 return _toDateAdvanced(o, alsoNumbers, timeZone, defaultValue, true); 387 } 388 389 private static DateTime _toDateAdvanced(Object o,boolean alsoNumbers, TimeZone timeZone, DateTime defaultValue, boolean advanced) { 390 if(o instanceof DateTime) return (DateTime)o; 391 else if(o instanceof Date) return new DateTimeImpl((Date)o); 392 else if(o instanceof Castable) { 393 return ((Castable)o).castToDateTime(defaultValue); 394 } 395 else if(o instanceof String) { 396 if(advanced)return toDateAdvanced(o.toString(),alsoNumbers, timeZone,defaultValue); 397 return toDateSimple(o.toString(),alsoNumbers,true, timeZone,defaultValue); 398 } 399 else if(alsoNumbers && o instanceof Number) return util.toDateTime(((Number)o).doubleValue()); 400 else if(o instanceof ObjectWrap) { 401 return _toDateAdvanced(((ObjectWrap)o).getEmbededObject(defaultValue),alsoNumbers,timeZone,defaultValue,advanced); 402 } 403 else if(o instanceof Calendar){ 404 return new DateTimeImpl((Calendar)o); 405 } 406 return defaultValue; 407 } 408 409 410 411 /** 412 * converts a Object to a DateTime Object, returns null if invalid string 413 * @param str Stringt to Convert 414 * @param alsoNumbers 415 * @param timeZone 416 * @return coverted Date Time Object 417 * @throws PageException 418 */ 419 public static DateTime toDateSimple(String str,boolean alsoNumbers,boolean alsoMonthString, TimeZone timeZone) throws PageException { 420 DateTime dt = toDateSimple(str,alsoNumbers,alsoMonthString,timeZone,null); 421 if(dt==null) throw new ExpressionException("can't cast value to a Date Object"); 422 return dt; 423 } 424 425 public static DateTime toDateAdvanced(Object o,boolean alsoNumbers, TimeZone timeZone) throws PageException { 426 DateTime dt = toDateAdvanced(o,alsoNumbers,timeZone,null); 427 if(dt==null) throw new ExpressionException("can't cast value to a Date Object"); 428 return dt; 429 } 430 431 432 433 /** 434 * converts a String to a Time Object, returns null if invalid string 435 * @param str String to convert 436 * @param defaultValue 437 * @return Time Object 438 * @throws 439 */ 440 public static Time toTime(TimeZone timeZone,String str, Time defaultValue) { 441 442 if(str==null || str.length()<3) { 443 return defaultValue; 444 } 445 DateString ds=new DateString(str); 446 // Timestamp 447 if(ds.isCurrent('{') && ds.isLast('}')) { 448 449 // Time 450 // "^\\{t '([0-9]{1,2}):([0-9]{1,2}):([0-9]{2})'\\}$" 451 if(ds.fwIfNext('t')) { 452 453 // Time 454 if(!(ds.fwIfNext(' ') && ds.fwIfNext('\'')))return defaultValue; 455 ds.next(); 456 // hour 457 int hour=ds.readDigits(); 458 if(hour==-1) return defaultValue; 459 460 if(!ds.fwIfCurrent(':'))return defaultValue; 461 462 // minute 463 int minute=ds.readDigits(); 464 if(minute==-1) return defaultValue; 465 466 if(!ds.fwIfCurrent(':'))return defaultValue; 467 468 // second 469 int second=ds.readDigits(); 470 if(second==-1) return defaultValue; 471 472 if(!(ds.fwIfCurrent('\'') && ds.fwIfCurrent('}')))return defaultValue; 473 474 if(ds.isAfterLast()){ 475 long time=util.toTime(timeZone,1899,12,30,hour,minute,second,0,DEFAULT_VALUE); 476 if(time==DEFAULT_VALUE)return defaultValue; 477 return new TimeImpl(time,false); 478 } 479 return defaultValue; 480 481 482 } 483 return defaultValue; 484 } 485 // Time start with int 486 /*else if(ds.isDigit()) { 487 char sec=ds.charAt(1); 488 char third=ds.charAt(2); 489 // 16.10.2004 (02:15)? 490 if(sec==':' || third==':') { 491 // hour 492 int hour=ds.readDigits(); 493 if(hour==-1) return defaultValue; 494 495 if(!ds.fwIfCurrent(':'))return defaultValue; 496 497 // minutes 498 int minutes=ds.readDigits(); 499 if(minutes==-1) return defaultValue; 500 501 if(ds.isAfterLast()) { 502 long time=util.toTime(timeZone,1899,12,30,hour,minutes,0,0,DEFAULT_VALUE); 503 if(time==DEFAULT_VALUE) return defaultValue; 504 505 return new TimeImpl(time,false); 506 } 507 //else if(!ds.fwIfCurrent(':'))return null; 508 else if(!ds.fwIfCurrent(':')) { 509 if(!ds.fwIfCurrent(' '))return defaultValue; 510 511 if(ds.fwIfCurrent('a') || ds.fwIfCurrent('A')) { 512 if(ds.fwIfCurrent('m') || ds.fwIfCurrent('M')) { 513 if(ds.isAfterLast()) { 514 long time=util.toTime(timeZone,1899,12,30,hour,minutes,0,0,DEFAULT_VALUE); 515 if(time==DEFAULT_VALUE) return defaultValue; 516 return new TimeImpl(time,false); 517 } 518 } 519 return defaultValue; 520 } 521 else if(ds.fwIfCurrent('p') || ds.fwIfCurrent('P')) { 522 if(ds.fwIfCurrent('m') || ds.fwIfCurrent('M')) { 523 if(ds.isAfterLast()) { 524 long time=util.toTime(timeZone,1899,12,30,hour<13?hour+12:hour,minutes,0,0,DEFAULT_VALUE); 525 if(time==DEFAULT_VALUE) return defaultValue; 526 return new TimeImpl(time,false); 527 } 528 } 529 return defaultValue; 530 } 531 return defaultValue; 532 } 533 534 535 // seconds 536 int seconds=ds.readDigits(); 537 if(seconds==-1) return defaultValue; 538 539 if(ds.isAfterLast()) { 540 long time=util.toTime(timeZone,1899,12,30,hour,minutes,seconds,0,DEFAULT_VALUE); 541 if(time==DEFAULT_VALUE) return defaultValue; 542 return new TimeImpl(time,false); 543 } 544 545 } 546 }*/ 547 548 // TODO bessere impl 549 ds.reset(); 550 DateTime rtn = parseTime(timeZone, new int[]{1899,12,30}, ds, defaultValue,-1); 551 if(rtn==defaultValue) return defaultValue; 552 return new TimeImpl(rtn); 553 554 555 556 //return defaultValue; 557 } 558 559 560 561 /** 562 * converts a String to a DateTime Object, returns null if invalid string 563 * @param str String to convert 564 * @param alsoNumbers 565 * @param alsoMonthString allow that the month is a english name 566 * @param timeZone 567 * @param defaultValue 568 * @return Date Time Object 569 */ 570 private static DateTime parseDateTime(String str,DateString ds,boolean alsoNumbers,boolean alsoMonthString,TimeZone timeZone, DateTime defaultValue) { 571 int month=0; 572 int first=ds.readDigits(); 573 // first 574 if(first==-1) { 575 if(!alsoMonthString) return defaultValue; 576 first=ds.readMonthString(); 577 if(first==-1)return defaultValue; 578 month=1; 579 } 580 581 if(ds.isAfterLast()) return month==1?defaultValue:toNumberDate(str,alsoNumbers,defaultValue); 582 583 char del=ds.current(); 584 if(del!='.' && del!='/' && del!='-' && del!=' ' && del!='\t') { 585 if(ds.fwIfCurrent(':')){ 586 return parseTime(timeZone, new int[]{1899,12,30}, ds, defaultValue,first); 587 } 588 return defaultValue; 589 } 590 ds.next(); 591 ds.removeWhitespace(); 592 593 // second 594 int second=ds.readDigits(); 595 if(second==-1){ 596 if(!alsoMonthString) return defaultValue; 597 second=ds.readMonthString(); 598 if(second==-1)return defaultValue; 599 month=2; 600 } 601 602 if(ds.isAfterLast()) { 603 return toDate(month,timeZone,first,second,defaultValue); 604 } 605 606 char del2=ds.current(); 607 if(del!=del2) { 608 ds.fwIfCurrent(' '); 609 ds.fwIfCurrent('T'); 610 ds.fwIfCurrent(' '); 611 return parseTime(timeZone,_toDate(timeZone,month, first, second),ds,defaultValue,-1); 612 } 613 ds.next(); 614 ds.removeWhitespace(); 615 616 617 618 int third=ds.readDigits(); 619 if(third==-1){ 620 return defaultValue; 621 } 622 623 if(ds.isAfterLast()) { 624 if(classicStyle() && del=='.')return toDate(month,timeZone,second,first,third,defaultValue); 625 return toDate(month,timeZone,first,second,third,defaultValue); 626 } 627 ds.fwIfCurrent(' '); 628 ds.fwIfCurrent('T'); 629 ds.fwIfCurrent(' '); 630 if(classicStyle() && del=='.')return parseTime(timeZone,_toDate(month, second,first,third),ds,defaultValue,-1); 631 return parseTime(timeZone,_toDate(month, first, second,third),ds,defaultValue,-1); 632 633 634 } 635 636 private static boolean classicStyle() { 637 return classicStyle; 638 } 639 640 private static DateTime parseTime(TimeZone timeZone,int[] date, DateString ds,DateTime defaultValue, int hours) { 641 if(date==null)return defaultValue; 642 643 644 ds.removeWhitespace(); 645 646 // hour 647 boolean next=false; 648 if(hours==-1){ 649 ds.removeWhitespace(); 650 hours=ds.readDigits(); 651 ds.removeWhitespace(); 652 if(hours==-1) { 653 return parseOffset(ds,timeZone,date,0,0,0,0,defaultValue); 654 } 655 } 656 else next=true; 657 658 int minutes=0; 659 if(next || ds.fwIfCurrent(':')){ 660 ds.removeWhitespace(); 661 minutes=ds.readDigits(); 662 ds.removeWhitespace(); 663 if(minutes==-1) return defaultValue; 664 } 665 666 667 int seconds=0; 668 if(ds.fwIfCurrent(':')){ 669 ds.removeWhitespace(); 670 seconds=ds.readDigits(); 671 ds.removeWhitespace(); 672 if(seconds==-1) return defaultValue; 673 } 674 675 int msSeconds=0; 676 if(ds.fwIfCurrent('.')){ 677 ds.removeWhitespace(); 678 msSeconds=ds.readDigits(); 679 ds.removeWhitespace(); 680 if(msSeconds==-1) return defaultValue; 681 } 682 683 if(ds.isAfterLast()){ 684 return DateTimeUtil.getInstance().toDateTime(timeZone, date[0], date[1], date[2], hours, minutes, seconds, msSeconds, defaultValue); 685 } 686 ds.fwIfCurrent(' '); 687 688 if(ds.fwIfCurrent('a') || ds.fwIfCurrent('A')) { 689 if(!ds.fwIfCurrent('m'))ds.fwIfCurrent('M'); 690 if(ds.isAfterLast()) 691 return DateTimeUtil.getInstance().toDateTime(timeZone, date[0], date[1], date[2], 692 hours<12?hours:hours-12, minutes, seconds, msSeconds, defaultValue); 693 return defaultValue; 694 } 695 else if(ds.fwIfCurrent('p') || ds.fwIfCurrent('P')) { 696 if(!ds.fwIfCurrent('m'))ds.fwIfCurrent('M'); 697 if(hours>24) return defaultValue; 698 if(ds.isAfterLast()) 699 return DateTimeUtil.getInstance().toDateTime(timeZone, date[0], date[1], date[2], 700 hours<12?hours+12:hours, minutes, seconds, msSeconds,defaultValue); 701 return defaultValue; 702 } 703 704 ds.fwIfCurrent(' '); 705 return parseOffset(ds,timeZone,date,hours,minutes,seconds,msSeconds,defaultValue); 706 707 } 708 709 private static DateTime parseOffset(DateString ds, TimeZone timeZone, int[] date,int hours, int minutes, int seconds, int msSeconds,DateTime defaultValue) { 710 if(ds.isLast() && (ds.fwIfCurrent('Z') || ds.fwIfCurrent('z'))) { 711 return util.toDateTime(TimeZoneConstants.UTC, date[0], date[1], date[2], hours, minutes, seconds, msSeconds,defaultValue); 712 } 713 else if(ds.fwIfCurrent('+')){ 714 DateTime rtn = util.toDateTime(timeZone, date[0], date[1], date[2], hours, minutes, seconds, msSeconds,defaultValue); 715 if(rtn==defaultValue) return rtn; 716 return readOffset(true,timeZone,rtn,date[0], date[1], date[2], hours, minutes, seconds, msSeconds,ds,defaultValue); 717 } 718 else if(ds.fwIfCurrent('-')){ 719 DateTime rtn = util.toDateTime(timeZone, date[0], date[1], date[2], hours, minutes, seconds, msSeconds, defaultValue); 720 if(rtn==defaultValue) return rtn; 721 return readOffset(false,timeZone,rtn,date[0], date[1], date[2], hours, minutes, seconds, msSeconds,ds,defaultValue); 722 } 723 return defaultValue; 724 } 725 726 private static DateTime toDate(int month, TimeZone timeZone,int first, int second, DateTime defaultValue) { 727 int[] d = _toDate(timeZone,month, first, second); 728 if(d==null)return defaultValue; 729 return util.toDateTime(timeZone, d[0], d[1], d[2],0,0,0,0,defaultValue); 730 } 731 732 private static int[] _toDate(TimeZone tz,int month, int first, int second) { 733 int YEAR=year(tz); 734 if(first<=12 && month<2){ 735 if(util.daysInMonth(YEAR, first)>=second) 736 return new int[]{YEAR, first, second}; 737 return new int[]{util.toYear(second), first, 1}; 738 } 739 // first>12 740 if(second<=12){ 741 if(util.daysInMonth(YEAR, second)>=first) 742 return new int[]{YEAR, second, first}; 743 return new int[]{util.toYear(first), second, 1}; 744 } 745 return null; 746 } 747 private static int year(TimeZone tz) { 748 return util.getYear(ThreadLocalPageContext.getTimeZone(tz),new DateTimeImpl()); 749 } 750 751 private static DateTime toDate(int month, TimeZone timeZone,int first, int second, int third, DateTime defaultValue) { 752 int[] d = _toDate(month, first, second, third); 753 if(d==null) return defaultValue; 754 return util.toDateTime(timeZone, d[0], d[1], d[2], 0, 0, 0,0,defaultValue); 755 } 756 757 private static int[] _toDate(int month, int first, int second, int third) { 758 if(first<=12){ 759 if(month==2) 760 return new int[]{util.toYear(third), second, first}; 761 if(util.daysInMonth(util.toYear(third), first)>=second) 762 return new int[]{util.toYear(third), first, second}; 763 return null; 764 } 765 if(second>12)return null; 766 if(month==2){ 767 int tmp=first; 768 first=third; 769 third=tmp; 770 } 771 if(util.daysInMonth(util.toYear(first), second)<third) { 772 if(util.daysInMonth(util.toYear(third), second)>=first) 773 return new int[]{util.toYear(third), second, first}; 774 return null; 775 } 776 return new int[]{util.toYear(first), second, third}; 777 } 778 779 /** 780 * converts the given string to a date following simple and fast parsing rules (no international formats) 781 * @param str 782 * @param alsoNumbers 783 * @param alsoMonthString allow that the month is defined as english word (jan,janauary ...) 784 * @param timeZone 785 * @param defaultValue 786 * @return 787 */ 788 public static DateTime toDateSimple(String str,boolean alsoNumbers,boolean alsoMonthString, TimeZone timeZone, DateTime defaultValue) { 789 str=StringUtil.trim(str,""); 790 DateString ds=new DateString(str); 791 792 // Timestamp 793 if(ds.isCurrent('{') && ds.isLast('}')) { 794 return _toDateSimpleTS(ds,timeZone,defaultValue); 795 } 796 DateTime res = parseDateTime(str,ds,alsoNumbers,alsoMonthString,timeZone,defaultValue); 797 if(alsoNumbers && res==defaultValue && Decision.isNumeric(str)) { 798 double dbl = Caster.toDoubleValue(str,Double.NaN); 799 if(Decision.isValid(dbl))return util.toDateTime(dbl); 800 } 801 return res; 802 } 803 804 private static DateTime _toDateSimpleTS(DateString ds, TimeZone timeZone, DateTime defaultValue) { 805 // Date 806 // "^\\{d '([0-9]{2,4})-([0-9]{1,2})-([0-9]{1,2})'\\}$" 807 if(ds.fwIfNext('d')) { 808 if(!(ds.fwIfNext(' ') && ds.fwIfNext('\'')))return defaultValue; 809 ds.next(); 810 // year 811 int year=ds.readDigits(); 812 if(year==-1) return defaultValue; 813 814 if(!ds.fwIfCurrent('-'))return defaultValue; 815 816 // month 817 int month=ds.readDigits(); 818 if(month==-1) return defaultValue; 819 820 if(!ds.fwIfCurrent('-'))return defaultValue; 821 822 // day 823 int day=ds.readDigits(); 824 if(day==-1) return defaultValue; 825 826 if(!(ds.fwIfCurrent('\'') && ds.fwIfCurrent('}')))return defaultValue; 827 828 if(ds.isAfterLast()) return util.toDateTime(timeZone,year, month, day, 0, 0, 0, 0, defaultValue);//new DateTimeImpl(year,month,day); 829 830 return defaultValue; 831 832 } 833 834 // DateTime 835 // "^\\{ts '([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{2}):([0-9]{1,2}):([0-9]{2})'\\}$" 836 else if(ds.fwIfNext('t')) { 837 if(!(ds.fwIfNext('s') && ds.fwIfNext(' ') && ds.fwIfNext('\''))) { 838 839 // Time 840 if(!(ds.fwIfNext(' ') && ds.fwIfNext('\'')))return defaultValue; 841 ds.next(); 842 // hour 843 int hour=ds.readDigits(); 844 if(hour==-1) return defaultValue; 845 846 if(!ds.fwIfCurrent(':'))return defaultValue; 847 848 // minute 849 int minute=ds.readDigits(); 850 if(minute==-1) return defaultValue; 851 852 if(!ds.fwIfCurrent(':'))return defaultValue; 853 854 // second 855 int second=ds.readDigits(); 856 if(second==-1) return defaultValue; 857 858 859 // Milli Second 860 int millis=0; 861 862 if(ds.fwIfCurrent('.')){ 863 millis=ds.readDigits(); 864 } 865 866 867 if(!(ds.fwIfCurrent('\'') && ds.fwIfCurrent('}')))return defaultValue; 868 869 870 871 if(ds.isAfterLast()){ 872 long time=util.toTime(timeZone,1899,12,30,hour,minute,second,millis,DEFAULT_VALUE); 873 if(time==DEFAULT_VALUE)return defaultValue; 874 return new TimeImpl(time,false); 875 } 876 return defaultValue; 877 } 878 ds.next(); 879 // year 880 int year=ds.readDigits(); 881 if(year==-1) return defaultValue; 882 883 if(!ds.fwIfCurrent('-'))return defaultValue; 884 885 // month 886 int month=ds.readDigits(); 887 if(month==-1) return defaultValue; 888 889 if(!ds.fwIfCurrent('-'))return defaultValue; 890 891 // day 892 int day=ds.readDigits(); 893 if(day==-1) return defaultValue; 894 895 if(!ds.fwIfCurrent(' '))return defaultValue; 896 897 // hour 898 int hour=ds.readDigits(); 899 if(hour==-1) return defaultValue; 900 901 if(!ds.fwIfCurrent(':'))return defaultValue; 902 903 // minute 904 int minute=ds.readDigits(); 905 if(minute==-1) return defaultValue; 906 907 if(!ds.fwIfCurrent(':'))return defaultValue; 908 909 // second 910 int second=ds.readDigits(); 911 if(second==-1) return defaultValue; 912 913 914 915 // Milli Second 916 int millis=0; 917 918 if(ds.fwIfCurrent('.')){ 919 millis=ds.readDigits(); 920 } 921 922 if(!(ds.fwIfCurrent('\'') && ds.fwIfCurrent('}')))return defaultValue; 923 if(ds.isAfterLast())return util.toDateTime(timeZone,year, month, day,hour,minute,second,millis,defaultValue);//new DateTimeImpl(year,month,day,hour,minute,second); 924 return defaultValue; 925 926 } 927 else return defaultValue; 928 } 929 930 private static DateTime toNumberDate(String str,boolean alsoNumbers, DateTime defaultValue) { 931 if(!alsoNumbers) return defaultValue; 932 double dbl = Caster.toDoubleValue(str,Double.NaN); 933 if(Decision.isValid(dbl))return util.toDateTime(dbl); 934 return defaultValue; 935 } 936 937 /** 938 * reads a offset definition at the end of a date string 939 * @param timeZone 940 * @param dt previous parsed date Object 941 * @param ds DateString to parse 942 * @param defaultValue 943 * @return date Object with offset 944 */ 945 private static DateTime readOffset(boolean isPlus,TimeZone timeZone,DateTime dt,int years, int months, int days, int hours, int minutes, int seconds, int milliSeconds, DateString ds,DateTime defaultValue) { 946 //timeZone=ThreadLocalPageContext.getTimeZone(timeZone); 947 if(timeZone==null) return defaultValue; 948 // HOUR 949 int hourLength=ds.getPos(); 950 int hour=ds.readDigits(); 951 hourLength=ds.getPos()-hourLength; 952 if(hour==-1) return defaultValue; 953 954 // MINUTE 955 int minute=0; 956 if(!ds.isAfterLast()) { 957 if(!ds.fwIfCurrent(':'))return defaultValue; 958 minute=ds.readDigits(); 959 if(minute==-1) return defaultValue; 960 961 } 962 else if(hourLength>2){ 963 int h=hour/100; 964 minute=hour-(h*100); 965 hour=h; 966 } 967 968 if(hour>12) return defaultValue; 969 if(minute>59) return defaultValue; 970 if(hour==12 && minute>0) return defaultValue; 971 972 long offset = hour*60L*60L*1000L; 973 offset+=minute*60*1000; 974 975 if(ds.isAfterLast()) { 976 long time= util.toTime(TimeZoneConstants.UTC, years, months, days, hours, minutes, seconds, milliSeconds, 0); 977 978 if(isPlus)time-=offset; 979 else time+=offset; 980 return new DateTimeImpl(time,false); 981 } 982 return defaultValue; 983 } 984 985 public static String toUSDate(Object o, TimeZone timeZone) throws PageException { 986 if(Decision.isUSDate(o)) return Caster.toString(o); 987 DateTime date = DateCaster.toDateAdvanced(o, timeZone); 988 return new railo.runtime.format.DateFormat(Locale.US).format(date,"mm/dd/yyyy"); 989 } 990 991 public static String toEuroDate(Object o, TimeZone timeZone) throws PageException { 992 if(Decision.isEuroDate(o)) return Caster.toString(o); 993 DateTime date = DateCaster.toDateAdvanced(o, timeZone); 994 return new railo.runtime.format.DateFormat(Locale.US).format(date,"dd.mm.yyyy"); 995 } 996 997 public static String toShortTime(long time) { 998 return Long.toString(time/1000,36); 999 } 1000 1001 public static long fromShortTime(String str) { 1002 return Long.parseLong(str,36)*1000; 1003 } 1004 }