KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > iapi > types > SQLTime


1 /*
2
3    Derby - Class org.apache.derby.iapi.types.SQLTime
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

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 JavaDoc;
49 import java.sql.Time JavaDoc;
50 import java.sql.Timestamp JavaDoc;
51 import java.sql.Types JavaDoc;
52 import java.sql.PreparedStatement JavaDoc;
53
54 import java.util.Calendar JavaDoc;
55 import java.util.GregorianCalendar JavaDoc;
56
57 import java.io.ObjectOutput JavaDoc;
58 import java.io.ObjectInput JavaDoc;
59 import java.io.IOException JavaDoc;
60
61 import java.sql.ResultSet JavaDoc;
62 import java.sql.SQLException JavaDoc;
63
64 import java.text.DateFormat JavaDoc;
65 import java.text.ParseException JavaDoc;
66
67 /**
68  * This contains an instance of a SQL Time
69  * Our current implementation doesn't implement time precision so the fractional
70  * seconds portion of the time is always 0. The default when no time precision
71  * is specified is 0 fractional seconds. A SQL Time without timezone information
72  * is assumed to be in the local time zone. The local time is stored as is
73  * and doesn't change if the timezone changes. This is in conformance with the
74  * SQL99 standard. The SQL92 standard indicates that the time is in GMT and
75  * changes with the timezone. The SQL99 standard clarifies this to allow time without
76  * timezoned to be stored as the local time.
77  * <p>
78  * Time is stored as two ints. The first int represents hour, minute, second
79  * and the second represents fractional seconds (currently 0 since we don't support
80  * time precision)
81  * encodedTime = -1 indicates null
82  *
83  * PERFORMANCE OPTIMIZATION:
84  * The java.sql.Time object is only instantiated on demand for performance
85  * reasons.
86  */

87
88 public final class SQLTime extends DataType
89                         implements DateTimeDataValue
90 {
91
92     private int encodedTime;
93     private int encodedTimeFraction; //currently always 0 since we don't
94
//support time precision
95

96     // The cached value.toString()
97
private String JavaDoc valueString;
98
99     /*
100     ** DataValueDescriptor interface
101     ** (mostly implemented in DataType)
102     */

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     } // end of estimateMemoryUsage
110

111     public String JavaDoc 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     /**
142      * Convert a SQL TIME to a JDBC java.sql.Timestamp.
143      *
144      * Behaviour is to set the date portion of the Timestamp
145      * to the actual current date, which may not match the
146      * SQL CURRENT DATE, which remains fixed for the lifetime
147      * of a SQL statement. JDBC drivers (especially network client drivers)
148      * could not be expected to fetch the CURRENT_DATE SQL value
149      * on every query that involved a TIME value, so the current
150      * date as seen by the JDBC client was picked as the logical behaviour.
151      * See DERBY-1811.
152      */

153     public Timestamp JavaDoc getTimestamp( Calendar JavaDoc cal)
154     {
155         if (isNull())
156             return null;
157         else
158         {
159             if( cal == null)
160             {
161                 // Calendar initialized to current date and time.
162
cal = new GregorianCalendar JavaDoc();
163             }
164             else
165             {
166                 cal.clear();
167                 // Set Calendar to current date and time.
168
cal.setTime(new Date JavaDoc(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             // Derby's resolution for the TIME type is only seconds.
176
cal.set(Calendar.MILLISECOND, 0);
177             
178             return new Timestamp JavaDoc(cal.getTime().getTime());
179         }
180     }
181
182     public Object JavaDoc getObject()
183     {
184         return getTime( (Calendar JavaDoc) null);
185     }
186         
187     public int getLength()
188     {
189         return 8;
190     }
191
192     /* this is for DataType's error generator */
193     public String JavaDoc getTypeName()
194     {
195         return "TIME";
196     }
197
198
199     /*
200      * Storable interface, implies Externalizable, TypedFormat
201      */

202
203     /**
204         Return my format identifier.
205
206         @see org.apache.derby.iapi.services.io.TypedFormat#getTypeFormatId
207     */

208     public int getTypeFormatId() {
209         return StoredFormatIds.SQL_TIME_ID;
210     }
211
212     /**
213         @exception IOException error writing data
214
215     */

216     public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc {
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     /**
226      * @see java.io.Externalizable#readExternal
227      *
228      * @exception IOException Thrown on error reading the object
229      */

230     public void readExternal(ObjectInput JavaDoc in) throws IOException JavaDoc
231     {
232         encodedTime = in.readInt();
233         encodedTimeFraction = in.readInt();
234         // reset cached values
235
valueString = null;
236     }
237     public void readExternalFromArray(ArrayInputStream in) throws IOException JavaDoc
238     {
239         encodedTime = in.readInt();
240         encodedTimeFraction = in.readInt();
241         // reset cached values
242
valueString = null;
243     }
244
245     /*
246      * DataValueDescriptor interface
247      */

248
249     /** @see DataValueDescriptor#getClone */
250     public DataValueDescriptor getClone()
251     {
252         // Call constructor with all of our info
253
return new SQLTime(encodedTime, encodedTimeFraction);
254     }
255
256     /**
257      * @see DataValueDescriptor#getNewNull
258      */

259     public DataValueDescriptor getNewNull()
260     {
261         return new SQLTime();
262     }
263     /**
264      * @see org.apache.derby.iapi.services.io.Storable#restoreToNull
265      *
266      */

267
268     public void restoreToNull()
269     {
270         encodedTime = -1;
271         encodedTimeFraction = 0;
272
273         // clear cached valueString
274
valueString = null;
275     }
276
277     /*
278      * DataValueDescriptor interface
279      */

280
281     /**
282      * @see DataValueDescriptor#setValueFromResultSet
283      *
284      * @exception SQLException Thrown on error
285      */

286     public void setValueFromResultSet(ResultSet JavaDoc resultSet, int colNumber,
287                                       boolean isNullable)
288         throws SQLException JavaDoc, StandardException
289     {
290             restoreToNull();
291             encodedTime = computeEncodedTime(resultSet.getTime(colNumber));
292             //need to set encodedTimeFraction when we implement time precision
293
}
294
295     /**
296      * Orderable interface
297      *
298      *
299      * @see org.apache.derby.iapi.types.Orderable
300      *
301      * @exception StandardException thrown on failure
302      */

303     public int compare(DataValueDescriptor other)
304         throws StandardException
305     {
306         /* Use compare method from dominant type, negating result
307          * to reflect flipping of sides.
308          */

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         /*
320          * thisNull otherNull return
321          * T T 0 (this == other)
322          * F T -1 (this < other)
323          * T F 1 (this > other)
324          */

325         if (thisNull || otherNull)
326         {
327             if (!thisNull) // otherNull must be true
328
return -1;
329             if (!otherNull) // thisNull must be true
330
return 1;
331             return 0;
332         }
333
334         /*
335             Neither are null compare them
336          */

337
338         int comparison;
339
340         /* get the comparison time values */
341         int otherEncodedTime = 0;
342
343         /* if the argument is another Time look up the value
344          * we have already taken care of Null
345          * ignoring encodedTimeFraction for now since it is always 0
346          * - need to change this when we support TIME(precision)
347          */

348         if (other instanceof SQLTime)
349         {
350             otherEncodedTime=((SQLTime)other).encodedTime;
351         }
352         else
353         {
354             /* O.K. have to do it the hard way and calculate the numeric value
355              * from the value
356              */

357             otherEncodedTime = computeEncodedTime(other.getTime( (Calendar JavaDoc) 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     /**
370         @exception StandardException thrown on error
371      */

372     public boolean compare(int op,
373                            DataValueDescriptor other,
374                            boolean orderedNulls,
375                            boolean unknownRV)
376         throws StandardException
377     {
378         if (!orderedNulls) // nulls are unordered
379
{
380             if (this.isNull() || other.isNull())
381                 return unknownRV;
382         }
383
384         /* Do the comparison */
385         return super.compare(op, other, orderedNulls, unknownRV);
386     }
387
388     /*
389     ** Class interface
390     */

391
392     /*
393     ** Constructors
394     */

395
396     /** no-arg constructor required by Formattable */
397     public SQLTime()
398     {
399         encodedTime = -1; //null value
400
}
401
402     public SQLTime(Time JavaDoc value) throws StandardException
403     {
404         parseTime(value);
405     }
406
407     private void parseTime(java.util.Date JavaDoc 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     /**
419      * Construct a time from a string. The allowed time formats are:
420      *<ol>
421      *<li>old ISO and IBM European standard: hh.mm[.ss]
422      *<li>IBM USA standard: hh[:mm] {AM | PM}
423      *<li>JIS & current ISO: hh:mm[:ss]
424      *</ol>
425      *
426      * @exception Standard exception if the syntax is invalid or the value is out of range.
427      */

428     public SQLTime( String JavaDoc timeStr, boolean isJdbcEscape, LocaleFinder localeFinder)
429         throws StandardException
430     {
431         parseTime( timeStr, isJdbcEscape, localeFinder, (Calendar JavaDoc) null);
432     }
433     
434     /**
435      * Construct a time from a string. The allowed time formats are:
436      *<ol>
437      *<li>old ISO and IBM European standard: hh.mm[.ss]
438      *<li>IBM USA standard: hh[:mm] {AM | PM}
439      *<li>JIS & current ISO: hh:mm[:ss]
440      *</ol>
441      *
442      * @exception Standard exception if the syntax is invalid or the value is out of range.
443      */

444     public SQLTime( String JavaDoc timeStr, boolean isJdbcEscape, LocaleFinder localeFinder, Calendar JavaDoc 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 JavaDoc[] AM_PM = {"AM", "PM"};
456     private static final char[] END_OF_STRING = {(char) 0};
457     
458     private void parseTime( String JavaDoc timeStr, boolean isJdbcEscape, LocaleFinder localeFinder, Calendar JavaDoc 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                 // IBM USA or JIS (new ISO)
492
minute = parser.parseInt( 2, false, US_OR_JIS_MINUTE_END, false);
493                 switch( parser.getCurrentSeparator())
494                 {
495                 case ' ':
496                     // IBM USA with minutes
497
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                     // default is end of string, meaning that the seconds part is zero.
511
}
512                 break;
513
514             case ' ':
515                 // IBM USA with minutes omitted
516
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) // AM
536
{
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) // PM
548
{
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             // See if it is a localized time or timestamp
560
timeStr = StringUtil.trimTrailing( timeStr);
561             DateFormat JavaDoc timeFormat = null;
562             if(localeFinder == null)
563                 timeFormat = DateFormat.getTimeInstance();
564             else if( cal == null)
565                 timeFormat = localeFinder.getTimeFormat();
566             else
567                 timeFormat = (DateFormat JavaDoc) 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 JavaDoc pe)
575             {
576                 // Maybe it is a localized timestamp
577
try
578                 {
579                     encodedTime = SQLTimestamp.parseLocalTimestamp( timeStr, localeFinder, cal)[1];
580                 }
581                 catch( ParseException JavaDoc 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     } // end of parseTime
591

592     /**
593      * Set the value from a correctly typed Time object.
594      * @throws StandardException
595      */

596     void setObject(Object JavaDoc theValue) throws StandardException
597     {
598         setValue((Time JavaDoc) 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 JavaDoc cal = new GregorianCalendar JavaDoc();
614             setValue(theValue.getTime( cal), cal);
615         }
616     }
617
618     /**
619         @see DateTimeDataValue#setValue
620
621         @exception StandardException thrown on failure.
622      */

623     public void setValue(Time JavaDoc value, Calendar JavaDoc cal) throws StandardException
624     {
625         restoreToNull();
626         encodedTime = computeEncodedTime(value, cal);
627     }
628
629     /**
630         @see DateTimeDataValue#setValue
631
632         @exception StandardException thrown on failure.
633      */

634     public void setValue(Timestamp JavaDoc value, Calendar JavaDoc cal) throws StandardException
635     {
636         restoreToNull();
637         encodedTime = computeEncodedTime(value, cal);
638     }
639
640
641     public void setValue(String JavaDoc 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 JavaDoc) null);
652         }
653     }
654
655     /*
656     ** SQL Operators
657     */

658
659     /**
660      * @see DateTimeDataValue#getYear
661      *
662      * @exception StandardException Thrown on error
663      */

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     /**
676      * @see DateTimeDataValue#getMonth
677      *
678      * @exception StandardException Thrown on error
679      */

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     /**
692      * @see DateTimeDataValue#getDate
693      *
694      * @exception StandardException Thrown on error
695      */

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     /**
708      * @see DateTimeDataValue#getHours
709      *
710      * @exception StandardException Thrown on error
711      */

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     /**
723      * @see DateTimeDataValue#getMinutes
724      *
725      * @exception StandardException Thrown on error
726      */

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     /**
738      * @see DateTimeDataValue#getSeconds
739      *
740      * @exception StandardException Thrown on error
741      */

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     /*
753     ** String display of value
754     */

755
756     public String JavaDoc toString()
757     {
758         if (isNull())
759         {
760             return "NULL";
761         }
762         else
763         {
764             return getTime( (Calendar JavaDoc) null).toString();
765         }
766     }
767
768     /*
769      * Hash code
770      */

771     public int hashCode()
772     {
773         if (isNull())
774         {
775             return 0;
776         }
777         // add 1 since 0 represents a valid time
778
return encodedTime + encodedTimeFraction + 1;
779
780     }
781
782     /** @see DataValueDescriptor#typePrecedence */
783     public int typePrecedence()
784     {
785         return TypeId.TIME_PRECEDENCE;
786     }
787
788     /**
789      * Check if the value is null.
790      *
791      * @return Whether or not value is logically null.
792      */

793     public final boolean isNull()
794     {
795         return (encodedTime == -1);
796     }
797
798     /**
799      * Get the time value
800      * Since this is a JDBC object we use the JDBC definition
801      * we use the JDBC definition, see JDBC API Tutorial and Reference
802      * section 47.3.12
803      * Date is set to Jan. 1, 1970
804      *
805      * @return The localized time value.
806      */

807     public Time JavaDoc getTime(java.util.Calendar JavaDoc cal)
808     {
809         if (isNull())
810             return null;
811
812         if( cal == null)
813             cal = new GregorianCalendar JavaDoc();
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); //only 0 fractional seconds currently
823
return new Time JavaDoc(cal.getTime().getTime());
824     }
825     /**
826      * Get the encoded hour value (may be different than hour value for
827      * current timezone if value encoded in a different timezone)
828      *
829      * @return hour value
830      */

831     protected static int getHour(int encodedTime)
832     {
833         return (encodedTime >>> 16) & 0xff;
834     }
835     /**
836      * Get the encoded minute value (may be different than the minute value for
837      * current timezone if value encoded in a different timezone)
838      *
839      * @return minute value
840      */

841     protected static int getMinute(int encodedTime)
842     {
843         return ((encodedTime >>> 8) & 0xff);
844     }
845     /**
846      * Get the encoded second value (may be different than the second value for
847      * current timezone if value encoded in a different timezone)
848      *
849      * @return second value
850      */

851     protected static int getSecond(int encodedTime)
852     {
853         return (encodedTime & 0xff);
854     }
855     /**
856      * Calculate the encoded time from a Calendar object
857      * encoded time is hour << 16 + min << 8 + sec
858      * this function is also used by SQLTimestamp
859      *
860      * @param cal calendar with time set
861      * @return encoded time
862      *
863      * @exception StandardException if the time is not in the DB2 range
864      */

865     static int computeEncodedTime(Calendar JavaDoc 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     /**
886      * Convert a time to a JDBC escape format string
887      *
888      * @param hour
889      * @param minute
890      * @param second
891      * @param sb The resulting string is appended to this StringBuffer
892      */

893     static void timeToString( int hour, int minute, int second, StringBuffer JavaDoc sb)
894     {
895         String JavaDoc hourStr = Integer.toString( hour);
896         String JavaDoc minStr = Integer.toString( minute);
897         String JavaDoc 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     } // end of timeToString
910

911     /**
912      * Get the String version from the encodedTime.
913      *
914      * @return string value.
915      */

916     protected static String JavaDoc encodedTimeToString(int encodedTime)
917     {
918         StringBuffer JavaDoc vstr = new StringBuffer JavaDoc();
919         timeToString( SQLTime.getHour(encodedTime), SQLTime.getMinute(encodedTime), SQLTime.getSecond(encodedTime), vstr);
920         return vstr.toString();
921     }
922
923     // International Support
924

925     /**
926      * International version of getString(). Overrides getNationalString
927      * in DataType for date, time, and timestamp.
928      *
929      * @exception StandardException Thrown on error
930      */

931     protected String JavaDoc getNationalString(LocaleFinder localeFinder) throws StandardException
932     {
933         if (isNull())
934         {
935             return getString();
936         }
937
938         return localeFinder.getTimeFormat().format(getTime( (Calendar JavaDoc) null));
939     }
940
941     /**
942      * Compute encoded time value
943      * Time is represented by hour << 16 + minute << 8 + seconds
944      */

945     private int computeEncodedTime(java.util.Date JavaDoc value) throws StandardException
946     {
947         return computeEncodedTime( value, (Calendar JavaDoc) null);
948     }
949
950     static int computeEncodedTime(java.util.Date JavaDoc value, Calendar JavaDoc currentCal) throws StandardException
951     {
952         if (value == null)
953             return -1;
954         if( currentCal == null)
955             currentCal = new GregorianCalendar JavaDoc();
956         currentCal.setTime(value);
957         return computeEncodedTime(currentCal);
958     }
959
960      /** Adding this method to ensure that super class' setInto method doesn't get called
961       * that leads to the violation of JDBC spec( untyped nulls ) when batching is turned on.
962       */

963     public void setInto(PreparedStatement JavaDoc ps, int position) throws SQLException JavaDoc, StandardException {
964
965               ps.setTime(position, getTime((Calendar JavaDoc) null));
966    }
967
968
969     /**
970      * Add a number of intervals to a datetime value. Implements the JDBC escape TIMESTAMPADD function.
971      *
972      * @param intervalType One of FRAC_SECOND_INTERVAL, SECOND_INTERVAL, MINUTE_INTERVAL, HOUR_INTERVAL,
973      * DAY_INTERVAL, WEEK_INTERVAL, MONTH_INTERVAL, QUARTER_INTERVAL, or YEAR_INTERVAL
974      * @param intervalCount The number of intervals to add
975      * @param currentDate Used to convert time to timestamp
976      * @param resultHolder If non-null a DateTimeDataValue that can be used to hold the result. If null then
977      * generate a new holder
978      *
979      * @return startTime + intervalCount intervals, as a timestamp
980      *
981      * @exception StandardException
982      */

983     public DateTimeDataValue timestampAdd( int intervalType,
984                                            NumberDataValue intervalCount,
985                                            java.sql.Date JavaDoc 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 JavaDoc currentDate) throws StandardException
993     {
994         return new SQLTimestamp( SQLDate.computeEncodedDate( currentDate, (Calendar JavaDoc) null),
995                                  getEncodedTime(),
996                                  0 /* nanoseconds */);
997     }
998     
999     /**
1000     * Finds the difference between two datetime values as a number of intervals. Implements the JDBC
1001     * TIMESTAMPDIFF escape function.
1002     *
1003     * @param intervalType One of FRAC_SECOND_INTERVAL, SECOND_INTERVAL, MINUTE_INTERVAL, HOUR_INTERVAL,
1004     * DAY_INTERVAL, WEEK_INTERVAL, MONTH_INTERVAL, QUARTER_INTERVAL, or YEAR_INTERVAL
1005     * @param time1
1006     * @param currentDate Used to convert time to timestamp
1007     * @param resultHolder If non-null a NumberDataValue that can be used to hold the result. If null then
1008     * generate a new holder
1009     *
1010     * @return the number of intervals by which this datetime is greater than time1
1011     *
1012     * @exception StandardException
1013     */

1014    public NumberDataValue timestampDiff( int intervalType,
1015                                          DateTimeDataValue time1,
1016                                          java.sql.Date JavaDoc currentDate,
1017                                          NumberDataValue resultHolder)
1018        throws StandardException
1019    {
1020        return toTimestamp( currentDate ).timestampDiff( intervalType, time1, currentDate, resultHolder);
1021    }
1022}
1023
1024
Popular Tags