1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14 
15 // -------------------------------------------------------------
16 // C matra datavision 1993
17 // Updated :
18 // -------------------------------------------------------------
19 
20 #include <Quantity_Date.hxx>
21 #include <Quantity_DateDefinitionError.hxx>
22 #include <Quantity_Period.hxx>
23 #include <Standard_OutOfRange.hxx>
24 
25 static int  month_table[12] = {
26   31,     // January
27   28,     // February
28   31,     // March
29   30,     // April
30   31,     // May
31   30,     // June
32   31,     // July
33   31,     // August
34   30,     // September
35   31,     // October
36   30,     // November
37   31};    // December
38 
39 static int SecondsByYear     = 365 * 24 * 3600 ; // Normal Year
40 static int SecondsByLeapYear = 366 * 24 * 3600 ; // Leap Year
41 
42 // -----------------------------------------
43 // Initialize a date to January,1 1979 00:00
44 // -----------------------------------------
45 
Quantity_Date()46 Quantity_Date::Quantity_Date(): mySec(0),myUSec(0) {}
47 
48 
49 
50 // -----------------------------------------------------------
51 // IsValid : Checks the validity of a date
52 // This is the complete way month, day, year, ... micro second
53 // -----------------------------------------------------------
54 
55 
IsValid(const Standard_Integer mm,const Standard_Integer dd,const Standard_Integer yy,const Standard_Integer hh,const Standard_Integer mn,const Standard_Integer ss,const Standard_Integer mis,const Standard_Integer mics)56 Standard_Boolean Quantity_Date::IsValid(const Standard_Integer mm,
57                                         const Standard_Integer dd,
58                                         const Standard_Integer yy,
59                                         const Standard_Integer hh,
60                                         const Standard_Integer mn,
61                                         const Standard_Integer ss,
62                                         const Standard_Integer mis,
63                                         const Standard_Integer mics){
64 
65 if (mm < 1 || mm > 12) return Standard_False;
66 
67 
68 if (yy < 1979 ) return Standard_False;
69 
70 
71 if ( Quantity_Date::IsLeap (yy) ) month_table[1] = 29;
72 else month_table[1] = 28;
73 
74 if (dd < 1 || dd > month_table[mm-1]) return Standard_False;
75 
76 
77 if (hh < 0 || hh > 23) return Standard_False;
78 
79 
80 if (mn < 0 || mn > 59) return Standard_False;
81 
82 
83 if (ss < 0 || ss > 59) return Standard_False;
84 
85 
86 if (mis < 0 || mis > 999) return Standard_False;
87 
88 
89 if (mics < 0 || mics > 999) return Standard_False;
90 
91 return Standard_True;
92 
93 }
94 
95 // -----------------------------------------------------------
96 // Initialize a Date :
97 // This is the complete way month, day, year, ... micro second
98 // -----------------------------------------------------------
99 
100 
Quantity_Date(const Standard_Integer mm,const Standard_Integer dd,const Standard_Integer yy,const Standard_Integer hh,const Standard_Integer mn,const Standard_Integer ss,const Standard_Integer mis,const Standard_Integer mics)101 Quantity_Date::Quantity_Date(const Standard_Integer mm,
102                        const Standard_Integer dd,
103                        const Standard_Integer yy,
104                        const Standard_Integer hh,
105                        const Standard_Integer mn,
106                        const Standard_Integer ss,
107                        const Standard_Integer mis,
108                        const Standard_Integer mics){
109 
110 SetValues (mm,dd,yy,hh,mn,ss,mis,mics);
111 }
112 
113 // ------------------------------------------------------------
114 // Set values of a Date :
115 // This is the complete way month, day, year, ... micro second
116 // ------------------------------------------------------------
117 
SetValues(const Standard_Integer mm,const Standard_Integer dd,const Standard_Integer yy,const Standard_Integer hh,const Standard_Integer mn,const Standard_Integer ss,const Standard_Integer mis,const Standard_Integer mics)118 void Quantity_Date::SetValues(const Standard_Integer mm,
119                            const Standard_Integer dd,
120                            const Standard_Integer yy,
121                            const Standard_Integer hh,
122                            const Standard_Integer mn,
123                            const Standard_Integer ss,
124                            const Standard_Integer mis,
125                            const Standard_Integer mics){
126 
127 Standard_Integer i;
128 
129 if ( ! Quantity_Date::IsValid (mm,dd,yy,hh,mn,ss,mis,mics))
130    throw Quantity_DateDefinitionError("Quantity_Date::Quantity_Date invalid parameters");
131 
132 if ( Quantity_Date::IsLeap (yy) ) month_table[1] = 29;
133 else month_table[1] = 28;
134 
135 mySec  = 0;
136 myUSec = 0;
137 for(i = 1979; i < yy; i++) {
138    if ( ! Quantity_Date::IsLeap (i) ) mySec += SecondsByYear;
139    else mySec += SecondsByLeapYear;
140    }
141 
142 for(i = 1; i< mm; i++) {
143    mySec += month_table[i-1] * 3600 * 24 ;
144    }
145 
146 
147 mySec  += 3600 * 24 * (dd-1);
148 
149 mySec  += 3600 * hh;
150 
151 mySec  += 60   * mn;
152 
153 mySec  += ss;
154 
155 myUSec += mis * 1000;
156 
157 myUSec += mics;
158 
159 }
160 
161 
162 // ---------------------------------------------
163 // Values : Returns the values of a date
164 // ~~~~~~
165 // ---------------------------------------------
166 
Values(Standard_Integer & mm,Standard_Integer & dd,Standard_Integer & yy,Standard_Integer & hh,Standard_Integer & mn,Standard_Integer & ss,Standard_Integer & mis,Standard_Integer & mics) const167 void Quantity_Date::Values(Standard_Integer& mm,
168                            Standard_Integer& dd,
169                            Standard_Integer& yy,
170                            Standard_Integer& hh,
171                            Standard_Integer& mn,
172                            Standard_Integer& ss,
173                            Standard_Integer& mis,
174                            Standard_Integer& mics)const{
175 
176 
177 Standard_Integer i,carry;
178 
179 
180 for(yy = 1979, carry = mySec ;; yy++) {
181    if ( ! Quantity_Date::IsLeap (yy) )
182       {
183       month_table[1] = 28; // normal year
184       if (carry >= SecondsByYear ) carry -= SecondsByYear;
185       else break;
186       }
187    else
188       {
189       month_table[1] = 29; // Leap year
190       if (carry >= SecondsByLeapYear) carry -= SecondsByLeapYear;
191       else break;
192       }
193    }
194 
195 
196 for(mm = 1 ; ; mm++) {
197    i = month_table[mm-1] * 3600 * 24;
198    if ( carry >= i ) carry -= i;
199    else break;
200    }
201 
202 i = 3600 * 24;
203 for(dd = 1 ; ; dd++) {
204    if ( carry >= i ) carry -= i;
205    else break;
206    }
207 
208 for(hh = 0 ; ; hh++) {
209    if ( carry >= 3600 ) carry -= 3600;
210    else break;
211    }
212 
213 for(mn = 0 ; ; mn++) {
214    if ( carry >= 60 ) carry -= 60;
215    else break;
216    }
217 
218 ss = carry;
219 
220 mis  = myUSec / 1000;
221 mics = myUSec - ( mis * 1000);
222 }
223 
224 
225 // ---------------------------------------------------------------------
226 // Difference : Subtract a date to a given date; the result is a period
227 // ~~~~~~~~~~   of time
228 // ---------------------------------------------------------------------
229 
Difference(const Quantity_Date & OtherDate)230 Quantity_Period Quantity_Date::Difference(const Quantity_Date& OtherDate){
231 
232 Standard_Integer i1,i2;
233 
234 if (mySec == 0 && myUSec == 0)
235      {
236      i1 = OtherDate.mySec;
237      i2 = OtherDate.myUSec;
238      }
239 else {
240      i1 = mySec  - OtherDate.mySec ;
241      i2 = myUSec - OtherDate.myUSec;
242      }
243 
244 if ( i1 >= 0 && i2 < 0 ) {
245    i1--;
246    i2 = 1000000 + i2 ;
247    }
248 else if ( i1 <0   && i2 >= 0 ) {
249    i1 = Abs(i1);
250    if ( i2 > 0 ){
251       i1--;
252       i2 = 1000000 - i2 ;
253     }
254 }
255 else if ( i1 <0   && i2 <  0 ) {
256    i1 = Abs(i1);
257    i2 = Abs(i2);
258 }
259 
260 Quantity_Period   result ( i1 , i2 );
261 
262 return (result);
263 }
264 
265 
266 // ------------------------------------------------------------------
267 // Subtract : subtracts a period to a date and returns a date.
268 // ~~~~~~~~
269 // ------------------------------------------------------------------
270 
Subtract(const Quantity_Period & During)271 Quantity_Date Quantity_Date::Subtract(const Quantity_Period& During){
272 
273 Standard_Integer ss,mics;
274 Quantity_Date result;
275 result.mySec  = mySec;
276 result.myUSec = myUSec;
277 During.Values (ss,mics);
278 
279 result.mySec  -= ss;
280 result.myUSec -= mics;
281 
282 if ( result.mySec >= 0 && result.myUSec < 0 ) {
283    result.mySec--;
284    result.myUSec = 1000000 + result.myUSec ;
285    }
286 
287 
288 if ( result.mySec <0   )
289    throw Quantity_DateDefinitionError(
290    "Quantity_Date::Subtract : The result date is anterior to Jan,1 1979");
291 
292 return (result);
293 
294 }
295 
296 
297 // ----------------------------------------------------------------------
298 // Add : Adds a period of time to a date
299 // ~~~
300 // ----------------------------------------------------------------------
Add(const Quantity_Period & During)301 Quantity_Date Quantity_Date::Add(const Quantity_Period& During){
302 
303 Quantity_Date result;
304 During.Values (result.mySec,result.myUSec);
305 result.mySec  += mySec;
306 result.myUSec += myUSec;
307 if ( result.myUSec >= 1000000 ) {
308    result.mySec++;
309    result.myUSec -= 1000000;
310    }
311 return (result);
312 }
313 
314 
315 // ----------------------------------------------------------------------
316 // Year : Return the year of a date
317 // ~~~~
318 // ----------------------------------------------------------------------
Year()319 Standard_Integer Quantity_Date::Year(){
320 Standard_Integer dummy, year;
321  Values(dummy, dummy, year, dummy, dummy, dummy, dummy, dummy);
322  return (year);
323 }
324 
325 
326 // ----------------------------------------------------------------------
327 // Month : Return the month of a date
328 // ~~~~~
329 // ----------------------------------------------------------------------
Month()330 Standard_Integer Quantity_Date::Month(){
331 Standard_Integer dummy, month;
332  Values(month, dummy, dummy, dummy, dummy, dummy, dummy, dummy);
333  return(month);
334 }
335 
336 // ----------------------------------------------------------------------
337 // Day : Return the day of a date
338 // ~~~
339 // ----------------------------------------------------------------------
340 
Day()341 Standard_Integer Quantity_Date::Day(){
342 Standard_Integer dummy, day;
343  Values(dummy, day, dummy, dummy, dummy, dummy, dummy, dummy);
344  return(day);
345 }
346 
347 // ----------------------------------------------------------------------
348 // hour : Return the hour of a date
349 // ~~~~
350 // ----------------------------------------------------------------------
351 
Hour()352 Standard_Integer Quantity_Date::Hour(){
353 Standard_Integer dummy, hour;
354  Values(dummy, dummy, dummy, hour, dummy, dummy, dummy, dummy);
355  return(hour);
356 }
357 
358 // ----------------------------------------------------------------------
359 // Minute : Return the minute of a date
360 // ~~~~~~
361 // ----------------------------------------------------------------------
362 
Minute()363 Standard_Integer Quantity_Date::Minute(){
364 Standard_Integer dummy, min;
365  Values(dummy, dummy, dummy, dummy, min, dummy, dummy, dummy);
366  return(min);
367 }
368 
369 // ----------------------------------------------------------------------
370 // Second : Return the second of a date
371 // ~~~~~~
372 // ----------------------------------------------------------------------
373 
Second()374 Standard_Integer Quantity_Date::Second(){
375 Standard_Integer dummy, sec;
376  Values(dummy, dummy, dummy, dummy, dummy, sec , dummy, dummy);
377  return(sec);
378 }
379 
380 // ----------------------------------------------------------------------
381 // millisecond : Return the millisecond of a date
382 // ~~~~~~~~~~~
383 // ----------------------------------------------------------------------
384 
MilliSecond()385 Standard_Integer Quantity_Date::MilliSecond(){
386 Standard_Integer dummy, msec;
387  Values(dummy, dummy, dummy, dummy, dummy, dummy, msec, dummy);
388 return(msec);
389 }
390 
391 // ----------------------------------------------------------------------
392 // Day : Return the day of a date
393 // ~~~
394 // ----------------------------------------------------------------------
395 
MicroSecond()396 Standard_Integer Quantity_Date::MicroSecond(){
397 Standard_Integer dummy, msec;
398  Values(dummy, dummy, dummy, dummy, dummy, dummy, dummy, msec);
399 return(msec);
400 }
401 
402 // ----------------------------------------------------------------------
403 // IsEarlier : Return true if the date is earlier than an other date
404 // ~~~~~~~~~
405 // ----------------------------------------------------------------------
406 
IsEarlier(const Quantity_Date & other) const407 Standard_Boolean Quantity_Date::IsEarlier(const Quantity_Date& other)const{
408 if (mySec < other.mySec) return Standard_True;
409 else if (mySec > other.mySec) return Standard_False;
410 else return ( ( myUSec < other.myUSec ) ? Standard_True : Standard_False);
411 }
412 
413 // ----------------------------------------------------------------------
414 // IsLater : Return true if the date is later than an other date
415 // ~~~~~~~
416 // ----------------------------------------------------------------------
417 
IsLater(const Quantity_Date & other) const418 Standard_Boolean Quantity_Date::IsLater(const Quantity_Date& other)const{
419 if (mySec > other.mySec) return Standard_True;
420 else if (mySec < other.mySec) return Standard_False;
421 else return ( ( myUSec > other.myUSec ) ? Standard_True : Standard_False);
422 }
423 
424 
425 // ----------------------------------------------------------------------
426 // IsEqual : Return true if the date is the same than an other date
427 // ~~~~~~~
428 // ----------------------------------------------------------------------
429 
IsEqual(const Quantity_Date & other) const430 Standard_Boolean Quantity_Date::IsEqual(const Quantity_Date& other)const{
431 return ( ( myUSec == other.myUSec &&
432            mySec  == other.mySec     ) ? Standard_True : Standard_False);
433 }
434 
435