1 21 22 package org.apache.derby.iapi.types; 23 24 import org.apache.derby.iapi.reference.SQLState; 25 26 import org.apache.derby.iapi.services.io.ArrayInputStream; 27 28 import org.apache.derby.iapi.services.context.ContextService; 29 30 import org.apache.derby.iapi.services.sanity.SanityManager; 31 import org.apache.derby.iapi.services.io.StoredFormatIds; 32 33 import org.apache.derby.iapi.error.StandardException; 34 35 import org.apache.derby.iapi.db.DatabaseContext; 36 37 import org.apache.derby.iapi.types.DataValueDescriptor; 38 import org.apache.derby.iapi.types.TypeId; 39 40 import org.apache.derby.iapi.types.DateTimeDataValue; 41 import org.apache.derby.iapi.types.NumberDataValue; 42 43 import org.apache.derby.iapi.types.DataType; 44 import org.apache.derby.iapi.services.i18n.LocaleFinder; 45 import org.apache.derby.iapi.services.cache.ClassSize; 46 import org.apache.derby.iapi.util.StringUtil; 47 48 import java.sql.Date ; 49 import java.sql.Time ; 50 import java.sql.Timestamp ; 51 import java.sql.Types ; 52 import java.sql.PreparedStatement ; 53 54 import java.util.Calendar ; 55 import java.util.GregorianCalendar ; 56 57 import java.io.ObjectOutput ; 58 import java.io.ObjectInput ; 59 import java.io.IOException ; 60 61 import java.sql.ResultSet ; 62 import java.sql.SQLException ; 63 64 import java.text.DateFormat ; 65 import java.text.ParseException ; 66 67 87 88 public final class SQLTime extends DataType 89 implements DateTimeDataValue 90 { 91 92 private int encodedTime; 93 private int encodedTimeFraction; 96 private String valueString; 98 99 103 104 private static final int BASE_MEMORY_USAGE = ClassSize.estimateBaseFromCatalog( SQLTime.class); 105 106 public int estimateMemoryUsage() 107 { 108 return BASE_MEMORY_USAGE + ClassSize.estimateMemoryUsage( valueString); 109 } 111 public String getString() 112 { 113 if (!isNull()) 114 { 115 if (valueString == null) 116 { 117 valueString = encodedTimeToString(encodedTime); 118 } 119 return valueString; 120 } 121 else 122 { 123 if (SanityManager.DEBUG) 124 { 125 if (valueString != null) 126 { 127 SanityManager.THROWASSERT( 128 "valueString expected to be null, not " + 129 valueString); 130 } 131 } 132 return null; 133 } 134 } 135 136 int getEncodedTime() 137 { 138 return encodedTime; 139 } 140 141 153 public Timestamp getTimestamp( Calendar cal) 154 { 155 if (isNull()) 156 return null; 157 else 158 { 159 if( cal == null) 160 { 161 cal = new GregorianCalendar (); 163 } 164 else 165 { 166 cal.clear(); 167 cal.setTime(new Date (System.currentTimeMillis())); 169 } 170 171 cal.set(Calendar.HOUR_OF_DAY, getHour(encodedTime)); 172 cal.set(Calendar.MINUTE, getMinute(encodedTime)); 173 cal.set(Calendar.SECOND, getSecond(encodedTime)); 174 175 cal.set(Calendar.MILLISECOND, 0); 177 178 return new Timestamp (cal.getTime().getTime()); 179 } 180 } 181 182 public Object getObject() 183 { 184 return getTime( (Calendar ) null); 185 } 186 187 public int getLength() 188 { 189 return 8; 190 } 191 192 193 public String getTypeName() 194 { 195 return "TIME"; 196 } 197 198 199 202 203 208 public int getTypeFormatId() { 209 return StoredFormatIds.SQL_TIME_ID; 210 } 211 212 216 public void writeExternal(ObjectOutput out) throws IOException { 217 218 if (SanityManager.DEBUG) 219 SanityManager.ASSERT(!isNull(), "writeExternal() is not supposed to be called for null values."); 220 221 out.writeInt(encodedTime); 222 out.writeInt(encodedTimeFraction); 223 } 224 225 230 public void readExternal(ObjectInput in) throws IOException 231 { 232 encodedTime = in.readInt(); 233 encodedTimeFraction = in.readInt(); 234 valueString = null; 236 } 237 public void readExternalFromArray(ArrayInputStream in) throws IOException 238 { 239 encodedTime = in.readInt(); 240 encodedTimeFraction = in.readInt(); 241 valueString = null; 243 } 244 245 248 249 250 public DataValueDescriptor getClone() 251 { 252 return new SQLTime(encodedTime, encodedTimeFraction); 254 } 255 256 259 public DataValueDescriptor getNewNull() 260 { 261 return new SQLTime(); 262 } 263 267 268 public void restoreToNull() 269 { 270 encodedTime = -1; 271 encodedTimeFraction = 0; 272 273 valueString = null; 275 } 276 277 280 281 286 public void setValueFromResultSet(ResultSet resultSet, int colNumber, 287 boolean isNullable) 288 throws SQLException , StandardException 289 { 290 restoreToNull(); 291 encodedTime = computeEncodedTime(resultSet.getTime(colNumber)); 292 } 294 295 303 public int compare(DataValueDescriptor other) 304 throws StandardException 305 { 306 309 if (typePrecedence() < other.typePrecedence()) 310 { 311 return - (other.compare(this)); 312 } 313 314 boolean thisNull, otherNull; 315 316 thisNull = this.isNull(); 317 otherNull = other.isNull(); 318 319 325 if (thisNull || otherNull) 326 { 327 if (!thisNull) return -1; 329 if (!otherNull) return 1; 331 return 0; 332 } 333 334 337 338 int comparison; 339 340 341 int otherEncodedTime = 0; 342 343 348 if (other instanceof SQLTime) 349 { 350 otherEncodedTime=((SQLTime)other).encodedTime; 351 } 352 else 353 { 354 357 otherEncodedTime = computeEncodedTime(other.getTime( (Calendar ) null)); 358 } 359 if (encodedTime < otherEncodedTime) 360 comparison = -1; 361 else if (encodedTime > otherEncodedTime) 362 comparison = 1; 363 else 364 comparison = 0; 365 366 return comparison; 367 } 368 369 372 public boolean compare(int op, 373 DataValueDescriptor other, 374 boolean orderedNulls, 375 boolean unknownRV) 376 throws StandardException 377 { 378 if (!orderedNulls) { 380 if (this.isNull() || other.isNull()) 381 return unknownRV; 382 } 383 384 385 return super.compare(op, other, orderedNulls, unknownRV); 386 } 387 388 391 392 395 396 397 public SQLTime() 398 { 399 encodedTime = -1; } 401 402 public SQLTime(Time value) throws StandardException 403 { 404 parseTime(value); 405 } 406 407 private void parseTime(java.util.Date value) throws StandardException 408 { 409 encodedTime = computeEncodedTime(value); 410 } 411 412 private SQLTime(int encodedTime, int encodedTimeFraction) { 413 this.encodedTime = encodedTime; 414 this.encodedTimeFraction = encodedTimeFraction; 415 } 416 417 418 428 public SQLTime( String timeStr, boolean isJdbcEscape, LocaleFinder localeFinder) 429 throws StandardException 430 { 431 parseTime( timeStr, isJdbcEscape, localeFinder, (Calendar ) null); 432 } 433 434 444 public SQLTime( String timeStr, boolean isJdbcEscape, LocaleFinder localeFinder, Calendar cal) 445 throws StandardException 446 { 447 parseTime( timeStr, isJdbcEscape, localeFinder, cal); 448 } 449 450 private static final char IBM_EUR_SEPARATOR = '.'; 451 private static final char[] IBM_EUR_SEPARATOR_OR_END = {IBM_EUR_SEPARATOR, (char) 0}; 452 static final char JIS_SEPARATOR = ':'; 453 private static final char[] US_OR_JIS_MINUTE_END = {JIS_SEPARATOR, ' ', (char) 0}; 454 private static final char[] ANY_SEPARATOR = { '.', ':', ' '}; 455 private static final String [] AM_PM = {"AM", "PM"}; 456 private static final char[] END_OF_STRING = {(char) 0}; 457 458 private void parseTime( String timeStr, boolean isJdbcEscape, LocaleFinder localeFinder, Calendar cal) 459 throws StandardException 460 { 461 boolean validSyntax = true; 462 DateTimeParser parser = new DateTimeParser( timeStr); 463 StandardException thrownSE = null; 464 int hour = 0; 465 int minute = 0; 466 int second = 0; 467 int amPm = -1; 468 try 469 { 470 if( parser.nextSeparator() == SQLTimestamp.DATE_SEPARATOR) 471 { 472 encodedTime = SQLTimestamp.parseDateOrTimestamp( parser, true)[1]; 473 valueString = parser.getTrimmedString(); 474 return; 475 } 476 hour = parser.parseInt( 2, true, ANY_SEPARATOR, false); 477 switch( parser.getCurrentSeparator()) 478 { 479 case IBM_EUR_SEPARATOR: 480 if( isJdbcEscape) 481 { 482 validSyntax = false; 483 break; 484 } 485 minute = parser.parseInt( 2, false, IBM_EUR_SEPARATOR_OR_END, false); 486 if( parser.getCurrentSeparator() == IBM_EUR_SEPARATOR) 487 second = parser.parseInt( 2, false, END_OF_STRING, false); 488 break; 489 490 case ':': 491 minute = parser.parseInt( 2, false, US_OR_JIS_MINUTE_END, false); 493 switch( parser.getCurrentSeparator()) 494 { 495 case ' ': 496 if( isJdbcEscape) 498 { 499 validSyntax = false; 500 break; 501 } 502 amPm = parser.parseChoice( AM_PM); 503 parser.checkEnd(); 504 break; 505 506 case JIS_SEPARATOR: 507 second = parser.parseInt( 2, false, END_OF_STRING, false); 508 break; 509 510 } 512 break; 513 514 case ' ': 515 if( isJdbcEscape) 517 { 518 validSyntax = false; 519 break; 520 } 521 amPm = parser.parseChoice( AM_PM); 522 break; 523 524 default: 525 validSyntax = false; 526 } 527 } 528 catch( StandardException se) 529 { 530 validSyntax = false; 531 thrownSE = se; 532 } 533 if( validSyntax) 534 { 535 if( amPm == 0) { 537 if( hour == 12) 538 { 539 if( minute == 0 && second == 0) 540 hour = 24; 541 else 542 hour = 0; 543 } 544 else if( hour > 12) 545 throw StandardException.newException( SQLState.LANG_DATE_RANGE_EXCEPTION); 546 } 547 else if( amPm == 1) { 549 if( hour < 12) 550 hour += 12; 551 else if( hour > 12) 552 throw StandardException.newException( SQLState.LANG_DATE_RANGE_EXCEPTION); 553 } 554 valueString = parser.checkEnd(); 555 encodedTime = computeEncodedTime( hour, minute, second); 556 } 557 else 558 { 559 timeStr = StringUtil.trimTrailing( timeStr); 561 DateFormat timeFormat = null; 562 if(localeFinder == null) 563 timeFormat = DateFormat.getTimeInstance(); 564 else if( cal == null) 565 timeFormat = localeFinder.getTimeFormat(); 566 else 567 timeFormat = (DateFormat ) localeFinder.getTimeFormat().clone(); 568 if( cal != null) 569 timeFormat.setCalendar( cal); 570 try 571 { 572 encodedTime = computeEncodedTime( timeFormat.parse( timeStr), cal); 573 } 574 catch( ParseException pe) 575 { 576 try 578 { 579 encodedTime = SQLTimestamp.parseLocalTimestamp( timeStr, localeFinder, cal)[1]; 580 } 581 catch( ParseException pe2) 582 { 583 if( thrownSE != null) 584 throw thrownSE; 585 throw StandardException.newException( SQLState.LANG_DATE_SYNTAX_EXCEPTION); 586 } 587 } 588 valueString = timeStr; 589 } 590 } 592 596 void setObject(Object theValue) throws StandardException 597 { 598 setValue((Time ) theValue); 599 } 600 601 protected void setFrom(DataValueDescriptor theValue) throws StandardException { 602 603 if (theValue instanceof SQLTime) { 604 restoreToNull(); 605 606 SQLTime tvst = (SQLTime) theValue; 607 encodedTime = tvst.encodedTime; 608 encodedTimeFraction = tvst.encodedTimeFraction; 609 610 } 611 else 612 { 613 Calendar cal = new GregorianCalendar (); 614 setValue(theValue.getTime( cal), cal); 615 } 616 } 617 618 623 public void setValue(Time value, Calendar cal) throws StandardException 624 { 625 restoreToNull(); 626 encodedTime = computeEncodedTime(value, cal); 627 } 628 629 634 public void setValue(Timestamp value, Calendar cal) throws StandardException 635 { 636 restoreToNull(); 637 encodedTime = computeEncodedTime(value, cal); 638 } 639 640 641 public void setValue(String theValue) 642 throws StandardException 643 { 644 restoreToNull(); 645 if (theValue != null) 646 { 647 DatabaseContext databaseContext = (DatabaseContext) ContextService.getContext(DatabaseContext.CONTEXT_ID); 648 parseTime( theValue, 649 false, 650 (databaseContext == null) ? null : databaseContext.getDatabase(), 651 (Calendar ) null); 652 } 653 } 654 655 658 659 664 public NumberDataValue getYear(NumberDataValue result) 665 throws StandardException 666 { 667 if (SanityManager.DEBUG) 668 { 669 SanityManager.ASSERT(!isNull(), "getYear called on null."); 670 } 671 throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE, 672 "getYear", "Time"); 673 } 674 675 680 public NumberDataValue getMonth(NumberDataValue result) 681 throws StandardException 682 { 683 if (SanityManager.DEBUG) 684 { 685 SanityManager.ASSERT(!isNull(), "getMonth called on null."); 686 } 687 throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE, 688 "getMonth", "Time"); 689 } 690 691 696 public NumberDataValue getDate(NumberDataValue result) 697 throws StandardException 698 { 699 if (SanityManager.DEBUG) 700 { 701 SanityManager.ASSERT(!isNull(), "getDate called on null."); 702 } 703 throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE, 704 "getDate", "Time"); 705 } 706 707 712 public NumberDataValue getHours(NumberDataValue result) 713 throws StandardException 714 { 715 if (SanityManager.DEBUG) 716 { 717 SanityManager.ASSERT(!isNull(), "getHours called on null"); 718 } 719 return SQLDate.setSource(getHour(encodedTime), result); 720 } 721 722 727 public NumberDataValue getMinutes(NumberDataValue result) 728 throws StandardException 729 { 730 if (SanityManager.DEBUG) 731 { 732 SanityManager.ASSERT(!isNull(), "getMinutes called on null"); 733 } 734 return SQLDate.setSource(getMinute(encodedTime), result); 735 } 736 737 742 public NumberDataValue getSeconds(NumberDataValue result) 743 throws StandardException 744 { 745 if (SanityManager.DEBUG) 746 { 747 SanityManager.ASSERT(!isNull(), "getMinutes called on null"); 748 } 749 return SQLDate.setSource(getSecond(encodedTime), result); 750 } 751 752 755 756 public String toString() 757 { 758 if (isNull()) 759 { 760 return "NULL"; 761 } 762 else 763 { 764 return getTime( (Calendar ) null).toString(); 765 } 766 } 767 768 771 public int hashCode() 772 { 773 if (isNull()) 774 { 775 return 0; 776 } 777 return encodedTime + encodedTimeFraction + 1; 779 780 } 781 782 783 public int typePrecedence() 784 { 785 return TypeId.TIME_PRECEDENCE; 786 } 787 788 793 public final boolean isNull() 794 { 795 return (encodedTime == -1); 796 } 797 798 807 public Time getTime(java.util.Calendar cal) 808 { 809 if (isNull()) 810 return null; 811 812 if( cal == null) 813 cal = new GregorianCalendar (); 814 815 cal.clear(); 816 cal.set(Calendar.YEAR, 1970); 817 cal.set(Calendar.MONTH, Calendar.JANUARY); 818 cal.set(Calendar.DATE, 1); 819 cal.set(Calendar.HOUR_OF_DAY, getHour(encodedTime)); 820 cal.set(Calendar.MINUTE, getMinute(encodedTime)); 821 cal.set(Calendar.SECOND, getSecond(encodedTime)); 822 cal.set(Calendar.MILLISECOND, 0); return new Time (cal.getTime().getTime()); 824 } 825 831 protected static int getHour(int encodedTime) 832 { 833 return (encodedTime >>> 16) & 0xff; 834 } 835 841 protected static int getMinute(int encodedTime) 842 { 843 return ((encodedTime >>> 8) & 0xff); 844 } 845 851 protected static int getSecond(int encodedTime) 852 { 853 return (encodedTime & 0xff); 854 } 855 865 static int computeEncodedTime(Calendar cal) throws StandardException 866 { 867 return computeEncodedTime(cal.get(Calendar.HOUR_OF_DAY), 868 cal.get(Calendar.MINUTE), 869 cal.get(Calendar.SECOND)); 870 } 871 872 static int computeEncodedTime( int hour, int minute, int second) throws StandardException 873 { 874 if( hour == 24) 875 { 876 if( minute != 0 || second != 0) 877 throw StandardException.newException( SQLState.LANG_DATE_RANGE_EXCEPTION); 878 } 879 else if( hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) 880 throw StandardException.newException( SQLState.LANG_DATE_RANGE_EXCEPTION); 881 882 return (hour << 16) + (minute << 8) + second; 883 } 884 885 893 static void timeToString( int hour, int minute, int second, StringBuffer sb) 894 { 895 String hourStr = Integer.toString( hour); 896 String minStr = Integer.toString( minute); 897 String secondStr = Integer.toString( second); 898 if (hourStr.length() == 1) 899 sb.append("0"); 900 sb.append( hourStr); 901 sb.append( JIS_SEPARATOR); 902 if (minStr.length() == 1) 903 sb.append("0"); 904 sb.append(minStr); 905 sb.append( JIS_SEPARATOR); 906 if (secondStr.length() == 1) 907 sb.append("0"); 908 sb.append(secondStr); 909 } 911 916 protected static String encodedTimeToString(int encodedTime) 917 { 918 StringBuffer vstr = new StringBuffer (); 919 timeToString( SQLTime.getHour(encodedTime), SQLTime.getMinute(encodedTime), SQLTime.getSecond(encodedTime), vstr); 920 return vstr.toString(); 921 } 922 923 925 931 protected String getNationalString(LocaleFinder localeFinder) throws StandardException 932 { 933 if (isNull()) 934 { 935 return getString(); 936 } 937 938 return localeFinder.getTimeFormat().format(getTime( (Calendar ) null)); 939 } 940 941 945 private int computeEncodedTime(java.util.Date value) throws StandardException 946 { 947 return computeEncodedTime( value, (Calendar ) null); 948 } 949 950 static int computeEncodedTime(java.util.Date value, Calendar currentCal) throws StandardException 951 { 952 if (value == null) 953 return -1; 954 if( currentCal == null) 955 currentCal = new GregorianCalendar (); 956 currentCal.setTime(value); 957 return computeEncodedTime(currentCal); 958 } 959 960 963 public void setInto(PreparedStatement ps, int position) throws SQLException , StandardException { 964 965 ps.setTime(position, getTime((Calendar ) null)); 966 } 967 968 969 983 public DateTimeDataValue timestampAdd( int intervalType, 984 NumberDataValue intervalCount, 985 java.sql.Date currentDate, 986 DateTimeDataValue resultHolder) 987 throws StandardException 988 { 989 return toTimestamp( currentDate).timestampAdd( intervalType, intervalCount, currentDate, resultHolder); 990 } 991 992 private SQLTimestamp toTimestamp(java.sql.Date currentDate) throws StandardException 993 { 994 return new SQLTimestamp( SQLDate.computeEncodedDate( currentDate, (Calendar ) null), 995 getEncodedTime(), 996 0 ); 997 } 998 999 1014 public NumberDataValue timestampDiff( int intervalType, 1015 DateTimeDataValue time1, 1016 java.sql.Date currentDate, 1017 NumberDataValue resultHolder) 1018 throws StandardException 1019 { 1020 return toTimestamp( currentDate ).timestampDiff( intervalType, time1, currentDate, resultHolder); 1021 } 1022} 1023 1024 | Popular Tags |