0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / Quantity / Quantity_Date.cxx
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
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
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
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
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
167 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
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
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 // ----------------------------------------------------------------------
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 // ----------------------------------------------------------------------
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 // ----------------------------------------------------------------------
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
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
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
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
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
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
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
407 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
418 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
430 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