1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 package org.apache.openoffice.comp.sdbc.dbtools.util;
23 
24 import java.math.BigInteger;
25 import java.util.StringTokenizer;
26 
27 import com.sun.star.util.Date;
28 import com.sun.star.util.DateTime;
29 import com.sun.star.util.Time;
30 
31 public class DBTypeConversion {
32     private static final int MAX_DAYS = 3636532;
33     private static Date standardDate = new Date((short)1, (short)1, (short)1900);
34     private static int aDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
35     private static final double fMilliSecondsPerDay = 86400000.0;
36 
safeParseDouble(String value)37     public static double safeParseDouble(String value) {
38         try {
39             return Double.parseDouble(value);
40         } catch (NumberFormatException numberFormatException) {
41             return 0.0;
42         }
43     }
44 
safeParseFloat(String value)45     public static float safeParseFloat(String value) {
46         try {
47             return Float.parseFloat(value);
48         } catch (NumberFormatException numberFormatException) {
49             return 0.0f;
50         }
51     }
52 
safeParseInt(String value)53     public static int safeParseInt(String value) {
54         try {
55             return Integer.parseInt(value);
56         } catch (NumberFormatException numberFormatException) {
57             return 0;
58         }
59     }
60 
safeParseLong(String value)61     public static long safeParseLong(String value) {
62         try {
63             return Long.parseLong(value);
64         } catch (NumberFormatException numberFormatException) {
65             return 0;
66         }
67     }
68 
unsignedLongToFloat(long value)69     public static float unsignedLongToFloat(long value) {
70         float f = value & 0x7fffFFFFffffFFFFL;
71         if (value < 0) {
72             f += 0x1p63f;
73         }
74         return f;
75     }
76 
unsignedLongToDouble(long value)77     public static double unsignedLongToDouble(long value) {
78         double d = value & 0x7fffFFFFffffFFFFL;
79         if (value < 0) {
80             d += 0x1p63f;
81         }
82         return d;
83     }
84 
toUnsignedInt(byte value)85     public static int toUnsignedInt(byte value) {
86         return value & 0xff;
87     }
88 
toUnsignedInt(short value)89     public static int toUnsignedInt(short value) {
90         return value & 0xffff;
91     }
92 
toUnsignedString(int value)93     public static String toUnsignedString(int value) {
94         return Long.toString(value & 0xffffFFFFL);
95     }
96 
toUnsignedString(long value)97     public static String toUnsignedString(long value) {
98         return new BigInteger(Long.toHexString(value), 16).toString();
99     }
100 
addDays(int nDays, Date _rDate)101     public static void addDays(int nDays, Date _rDate) {
102         int   nTempDays = implRelativeToAbsoluteNull( _rDate );
103 
104         nTempDays += nDays;
105         if ( nTempDays > MAX_DAYS )
106         {
107             _rDate.Day      = 31;
108             _rDate.Month    = 12;
109             _rDate.Year     = 9999;
110         }
111         else if ( nTempDays <= 0 )
112         {
113             _rDate.Day      = 1;
114             _rDate.Month    = 1;
115             _rDate.Year     = 00;
116         }
117         else
118             implBuildFromRelative( nTempDays, _rDate );
119     }
120 
subDays(int nDays, Date _rDate)121     public static void subDays(int nDays, Date _rDate) {
122         int   nTempDays = implRelativeToAbsoluteNull( _rDate );
123 
124         nTempDays -= nDays;
125         if ( nTempDays > MAX_DAYS )
126         {
127             _rDate.Day      = 31;
128             _rDate.Month    = 12;
129             _rDate.Year     = 9999;
130         }
131         else if ( nTempDays <= 0 )
132         {
133             _rDate.Day      = 1;
134             _rDate.Month    = 1;
135             _rDate.Year     = 00;
136         }
137         else
138             implBuildFromRelative( nTempDays, _rDate );
139     }
140 
getMsFromTime(final Time rVal)141     public static int getMsFromTime(final Time rVal) {
142         int   nHour     = rVal.Hours;
143         int   nMin      = rVal.Minutes;
144         int   nSec      = rVal.Seconds;
145         int   n100Sec   = rVal.HundredthSeconds;
146 
147         return ((nHour*3600000)+(nMin*60000)+(nSec*1000)+(n100Sec*10));
148     }
149 
getStandardDate()150     public static Date getStandardDate() {
151         return standardDate;
152     }
153 
implDaysInMonth(int _nMonth, int _nYear)154     private static int implDaysInMonth(int _nMonth, int _nYear) {
155         if (_nMonth != 2)
156             return aDaysInMonth[_nMonth-1];
157         else {
158             if (implIsLeapYear(_nYear))
159                 return aDaysInMonth[_nMonth-1] + 1;
160             else
161                 return aDaysInMonth[_nMonth-1];
162         }
163     }
164 
implBuildFromRelative( int nDays, Date date )165     private static void implBuildFromRelative( int nDays, Date date ) {
166         int   nTempDays;
167         int   i = 0;
168         boolean    bCalc;
169 
170         do {
171             nTempDays = nDays;
172             date.Year = (short)((nTempDays / 365) - i);
173             nTempDays -= (date.Year-1) * 365;
174             nTempDays -= ((date.Year-1) / 4) - ((date.Year-1) / 100) + ((date.Year-1) / 400);
175             bCalc = false;
176             if ( nTempDays < 1 )
177             {
178                 i++;
179                 bCalc = true;
180             }
181             else
182             {
183                 if ( nTempDays > 365 )
184                 {
185                     if ( (nTempDays != 366) || !implIsLeapYear( date.Year ) )
186                     {
187                         i--;
188                         bCalc = true;
189                     }
190                 }
191             }
192         }
193         while ( bCalc );
194 
195         date.Month = 1;
196         while ( nTempDays > implDaysInMonth( date.Month, date.Year ) )
197         {
198             nTempDays -= implDaysInMonth( date.Month, date.Year );
199             date.Month++;
200         }
201         date.Day = (short)nTempDays;
202     }
203 
implIsLeapYear(int _nYear)204     private static boolean implIsLeapYear(int _nYear) {
205         return  (   (   ((_nYear % 4) == 0)
206                     &&  ((_nYear % 100) != 0)
207                     )
208                 )
209                 ||  ((_nYear % 400) == 0)
210                 ;
211     }
212 
213 
implRelativeToAbsoluteNull(final Date _rDate)214     private static int implRelativeToAbsoluteNull(final Date _rDate) {
215         int nDays = 0;
216 
217         // ripped this code from the implementation of tools::Date
218         int nNormalizedYear = _rDate.Year - 1;
219         nDays = nNormalizedYear * 365;
220         // leap years
221         nDays += (nNormalizedYear / 4) - (nNormalizedYear / 100) + (nNormalizedYear / 400);
222 
223         for (int i = 1; i < _rDate.Month; ++i)
224             nDays += implDaysInMonth(i, _rDate.Year);
225 
226         nDays += _rDate.Day;
227         return nDays;
228     }
229 
toDays(Date rVal)230     public static int toDays(Date rVal) {
231         return toDays(rVal, getStandardDate());
232     }
233 
toDays(Date rVal, Date rNullDate)234     public static int toDays(Date rVal, Date rNullDate) {
235         return implRelativeToAbsoluteNull(rVal) - implRelativeToAbsoluteNull(rNullDate);
236     }
237 
toDouble(Date rVal)238     public static double toDouble(Date rVal) {
239         return toDouble(rVal, getStandardDate());
240     }
241 
toDouble(Date rVal, Date _rNullDate)242     public static double toDouble(Date rVal, Date _rNullDate) {
243         return (double)toDays(rVal, _rNullDate);
244     }
245 
toDouble(DateTime _rVal)246     public static double toDouble(DateTime _rVal) {
247         return toDouble(_rVal, getStandardDate());
248     }
249 
toDouble(DateTime _rVal, Date _rNullDate)250     public static double toDouble(DateTime _rVal, Date _rNullDate) {
251         long   nTime     = toDays(new Date(_rVal.Day, _rVal.Month, _rVal.Year), _rNullDate);
252         Time aTimePart = new Time();
253 
254         aTimePart.Hours             = _rVal.Hours;
255         aTimePart.Minutes           = _rVal.Minutes;
256         aTimePart.Seconds           = _rVal.Seconds;
257         aTimePart.HundredthSeconds  = _rVal.HundredthSeconds;
258 
259         return ((double)nTime) + toDouble(aTimePart);
260     }
261 
toDouble(Time rVal)262     public static double toDouble(Time rVal) {
263         return (double)getMsFromTime(rVal) / fMilliSecondsPerDay;
264     }
265 
toDate(double dVal)266     public static Date toDate(double dVal) {
267         return toDate(dVal, getStandardDate());
268     }
269 
toDate(double dVal, Date _rNullDate)270     public static Date toDate(double dVal, Date _rNullDate) {
271         Date aRet = _rNullDate;
272 
273         if (dVal >= 0)
274             addDays((int)dVal,aRet);
275         else
276             subDays((int)(-dVal),aRet);
277             //  x -= (sal_uInt32)(-nDays);
278 
279         return aRet;
280     }
281 
toDate(String value)282     public static Date toDate(String value) {
283         String[] tokens = value.split("-");
284 
285         short  nYear   = 0,
286                 nMonth  = 0,
287                 nDay    = 0;
288         if (tokens.length > 0) {
289             nYear   = (short)safeParseInt(tokens[0]);
290         }
291         if (tokens.length > 1) {
292             nMonth = (short)safeParseInt(tokens[1]);
293         }
294         if (tokens.length > 2) {
295             nDay = (short)safeParseInt(tokens[2]);
296         }
297 
298         return new Date(nDay,nMonth,nYear);
299     }
300 
toDateTime(double dVal)301     public static DateTime toDateTime(double dVal) {
302         return toDateTime(dVal, getStandardDate());
303     }
304 
toDateTime(double dVal, Date _rNullDate)305     public static DateTime toDateTime(double dVal, Date _rNullDate) {
306         Date aDate = toDate(dVal, _rNullDate);
307         Time aTime = toTime(dVal);
308 
309         DateTime xRet = new DateTime();
310 
311         xRet.Day                = aDate.Day;
312         xRet.Month              = aDate.Month;
313         xRet.Year               = aDate.Year;
314 
315         xRet.HundredthSeconds   = aTime.HundredthSeconds;
316         xRet.Minutes            = aTime.Minutes;
317         xRet.Seconds            = aTime.Seconds;
318         xRet.Hours              = aTime.Hours;
319 
320 
321         return xRet;
322     }
323 
toDateTime(String _sSQLString)324     public static DateTime toDateTime(String _sSQLString) {
325         // the date part
326         int nSeparation = _sSQLString.indexOf( ' ' );
327         String dateString;
328         String timeString = "";
329         if (nSeparation >= 0) {
330             dateString = _sSQLString.substring(0, nSeparation);
331             timeString = _sSQLString.substring(nSeparation + 1);
332         } else {
333             dateString = _sSQLString;
334         }
335         Date aDate = toDate(dateString);
336         Time aTime = new Time();
337 
338         if ( -1 != nSeparation )
339             aTime = toTime( timeString );
340 
341         return new DateTime(aTime.HundredthSeconds,aTime.Seconds,aTime.Minutes,aTime.Hours,aDate.Day,aDate.Month,aDate.Year);
342     }
343 
toTime(int _nVal)344     public static Time toTime(int _nVal) {
345         Time aReturn = new Time();
346         aReturn.Hours = (short)(((int)(_nVal >= 0 ? _nVal : _nVal*-1)) / 1000000);
347         aReturn.Minutes = (short)((((int)(_nVal >= 0 ? _nVal : _nVal*-1)) / 10000) % 100);
348         aReturn.Seconds = (short)((((int)(_nVal >= 0 ? _nVal : _nVal*-1)) / 100) % 100);
349         aReturn.HundredthSeconds = (short)(((int)(_nVal >= 0 ? _nVal : _nVal*-1)) % 100);
350         return aReturn;
351     }
352 
toTime(double dVal)353     public static Time toTime(double dVal) {
354         int nDays     = (int)dVal;
355         int nMS = (int)((dVal - (double)nDays) * fMilliSecondsPerDay + 0.5);
356 
357         short nSign;
358         if ( nMS < 0 )
359         {
360             nMS *= -1;
361             nSign = -1;
362         }
363         else
364             nSign = 1;
365 
366         Time xRet = new Time();
367         // Zeit normalisieren
368         // we have to sal_Int32 here because otherwise we get an overflow
369         int nHundredthSeconds = nMS/10;
370         int nSeconds          = nHundredthSeconds / 100;
371         int nMinutes          = nSeconds / 60;
372 
373         xRet.HundredthSeconds       = (short)(nHundredthSeconds % 100);
374         xRet.Seconds                = (short)(nSeconds % 60);
375         xRet.Hours                  = (short)(nMinutes / 60);
376         xRet.Minutes                = (short)(nMinutes % 60);
377 
378         // Zeit zusammenbauen
379         int nTime = (int)(xRet.HundredthSeconds + (xRet.Seconds*100) + (xRet.Minutes*10000) + (xRet.Hours*1000000)) * nSign;
380 
381         if(nTime < 0)
382         {
383             xRet.HundredthSeconds   = 99;
384             xRet.Minutes            = 59;
385             xRet.Seconds            = 59;
386             xRet.Hours              = 23;
387         }
388         return xRet;
389     }
390 
toTime(String _sSQLString)391     public static Time toTime(String _sSQLString) {
392         short  nHour   = 0,
393                     nMinute = 0,
394                     nSecond = 0,
395                     nHundredthSeconds   = 0;
396         StringTokenizer tokenizer = new StringTokenizer(_sSQLString, ":");
397         if (tokenizer.hasMoreTokens()) {
398             nHour = (short)safeParseInt(tokenizer.nextToken());
399         }
400         if (tokenizer.hasMoreTokens()) {
401             nMinute = (short)safeParseInt(tokenizer.nextToken());
402         }
403         if (tokenizer.hasMoreTokens()) {
404             String secondAndNano = tokenizer.nextToken();
405             int dot = secondAndNano.indexOf(".");
406             if (dot >= 0) {
407                 nSecond = (short)safeParseInt(secondAndNano.substring(0, dot));
408                 String nano = secondAndNano.substring(dot + 1);
409                 if (nano.length() > 2) {
410                     nano = nano.substring(0, 2);
411                 }
412                 nano = nano + "00".substring(0, 2 - nano.length());
413                 nHundredthSeconds = (short)safeParseInt(nano);
414             } else {
415                 nSecond = (short)safeParseInt(secondAndNano);
416             }
417         }
418         return new Time(nHundredthSeconds,nSecond,nMinute,nHour);
419     }
420 
421     /// Return the date in the format %04d-%02d-%02d.
toDateString(Date date)422     public static String toDateString(Date date) {
423         return String.format("%04d-%02d-%02d",
424                 toUnsignedInt(date.Year),
425                 toUnsignedInt(date.Month),
426                 toUnsignedInt(date.Day));
427     }
428 
429     /// Return the time in the format %02d:%02d:%02d.
toTimeString(Time time)430     public static String toTimeString(Time time) {
431         return String.format("%02d:%02d:%02d",
432                 toUnsignedInt(time.Hours),
433                 toUnsignedInt(time.Minutes),
434                 toUnsignedInt(time.Seconds));
435     }
436 
437     /// Return the DateTime in the format %04d-%02d-%02d %02d:%02d:%02d.%d.
toDateTimeString(DateTime dateTime)438     public static String toDateTimeString(DateTime dateTime) {
439         return String.format("%04d-%02d-%02d %02d:%02d:%02d.%d",
440                 toUnsignedInt(dateTime.Year),
441                 toUnsignedInt(dateTime.Month),
442                 toUnsignedInt(dateTime.Day),
443                 toUnsignedInt(dateTime.Hours),
444                 toUnsignedInt(dateTime.Minutes),
445                 toUnsignedInt(dateTime.Seconds),
446                 toUnsignedInt(dateTime.HundredthSeconds));
447     }
448 }
449