1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 // -------------------------------------------------------------
16 // C matra datavision 1993
18 // -------------------------------------------------------------
20 #include <Quantity_Date.hxx>
21 #include <Quantity_DateDefinitionError.hxx>
22 #include <Quantity_Period.hxx>
23 #include <Standard_OutOfRange.hxx>
25 static int month_table[12] = {
39 static int SecondsByYear = 365 * 24 * 3600 ; // Normal Year
40 static int SecondsByLeapYear = 366 * 24 * 3600 ; // Leap Year
42 // -----------------------------------------
43 // Initialize a date to January,1 1979 00:00
44 // -----------------------------------------
46 Quantity_Date::Quantity_Date(): mySec(0),myUSec(0) {}
50 // -----------------------------------------------------------
51 // IsValid : Checks the validity of a date
52 // This is the complete way month, day, year, ... micro second
53 // -----------------------------------------------------------
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){
65 if (mm < 1 || mm > 12) return Standard_False;
68 if (yy < 1979 ) return Standard_False;
71 if ( Quantity_Date::IsLeap (yy) ) month_table[1] = 29;
72 else month_table[1] = 28;
74 if (dd < 1 || dd > month_table[mm-1]) return Standard_False;
77 if (hh < 0 || hh > 23) return Standard_False;
80 if (mn < 0 || mn > 59) return Standard_False;
83 if (ss < 0 || ss > 59) return Standard_False;
86 if (mis < 0 || mis > 999) return Standard_False;
89 if (mics < 0 || mics > 999) return Standard_False;
95 // -----------------------------------------------------------
96 // Initialize a Date :
97 // This is the complete way month, day, year, ... micro second
98 // -----------------------------------------------------------
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){
110 SetValues (mm,dd,yy,hh,mn,ss,mis,mics);
113 // ------------------------------------------------------------
114 // Set values of a Date :
115 // This is the complete way month, day, year, ... micro second
116 // ------------------------------------------------------------
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){
129 if ( ! Quantity_Date::IsValid (mm,dd,yy,hh,mn,ss,mis,mics))
130 throw Quantity_DateDefinitionError("Quantity_Date::Quantity_Date invalid parameters");
132 if ( Quantity_Date::IsLeap (yy) ) month_table[1] = 29;
133 else month_table[1] = 28;
137 for(i = 1979; i < yy; i++) {
138 if ( ! Quantity_Date::IsLeap (i) ) mySec += SecondsByYear;
139 else mySec += SecondsByLeapYear;
142 for(i = 1; i< mm; i++) {
143 mySec += month_table[i-1] * 3600 * 24 ;
147 mySec += 3600 * 24 * (dd-1);
155 myUSec += mis * 1000;
162 // ---------------------------------------------
163 // Values : Returns the values of a date
165 // ---------------------------------------------
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{
177 Standard_Integer i,carry;
180 for(yy = 1979, carry = mySec ;; yy++) {
181 if ( ! Quantity_Date::IsLeap (yy) )
183 month_table[1] = 28; // normal year
184 if (carry >= SecondsByYear ) carry -= SecondsByYear;
189 month_table[1] = 29; // Leap year
190 if (carry >= SecondsByLeapYear) carry -= SecondsByLeapYear;
196 for(mm = 1 ; ; mm++) {
197 i = month_table[mm-1] * 3600 * 24;
198 if ( carry >= i ) carry -= i;
203 for(dd = 1 ; ; dd++) {
204 if ( carry >= i ) carry -= i;
208 for(hh = 0 ; ; hh++) {
209 if ( carry >= 3600 ) carry -= 3600;
213 for(mn = 0 ; ; mn++) {
214 if ( carry >= 60 ) carry -= 60;
221 mics = myUSec - ( mis * 1000);
225 // ---------------------------------------------------------------------
226 // Difference : Subtract a date to a given date; the result is a period
227 // ~~~~~~~~~~ of time
228 // ---------------------------------------------------------------------
230 Quantity_Period Quantity_Date::Difference(const Quantity_Date& OtherDate){
232 Standard_Integer i1,i2;
234 if (mySec == 0 && myUSec == 0)
236 i1 = OtherDate.mySec;
237 i2 = OtherDate.myUSec;
240 i1 = mySec - OtherDate.mySec ;
241 i2 = myUSec - OtherDate.myUSec;
244 if ( i1 >= 0 && i2 < 0 ) {
248 else if ( i1 <0 && i2 >= 0 ) {
255 else if ( i1 <0 && i2 < 0 ) {
260 Quantity_Period result ( i1 , i2 );
266 // ------------------------------------------------------------------
267 // Subtract : subtracts a period to a date and returns a date.
269 // ------------------------------------------------------------------
271 Quantity_Date Quantity_Date::Subtract(const Quantity_Period& During){
273 Standard_Integer ss,mics;
274 Quantity_Date result;
275 result.mySec = mySec;
276 result.myUSec = myUSec;
277 During.Values (ss,mics);
280 result.myUSec -= mics;
282 if ( result.mySec >= 0 && result.myUSec < 0 ) {
284 result.myUSec = 1000000 + result.myUSec ;
288 if ( result.mySec <0 )
289 throw Quantity_DateDefinitionError(
290 "Quantity_Date::Subtract : The result date is anterior to Jan,1 1979");
297 // ----------------------------------------------------------------------
298 // Add : Adds a period of time to a date
300 // ----------------------------------------------------------------------
301 Quantity_Date Quantity_Date::Add(const Quantity_Period& During){
303 Quantity_Date result;
304 During.Values (result.mySec,result.myUSec);
305 result.mySec += mySec;
306 result.myUSec += myUSec;
307 if ( result.myUSec >= 1000000 ) {
309 result.myUSec -= 1000000;
315 // ----------------------------------------------------------------------
316 // Year : Return the year of a date
318 // ----------------------------------------------------------------------
319 Standard_Integer Quantity_Date::Year(){
320 Standard_Integer dummy, year;
321 Values(dummy, dummy, year, dummy, dummy, dummy, dummy, dummy);
326 // ----------------------------------------------------------------------
327 // Month : Return the month of a date
329 // ----------------------------------------------------------------------
330 Standard_Integer Quantity_Date::Month(){
331 Standard_Integer dummy, month;
332 Values(month, dummy, dummy, dummy, dummy, dummy, dummy, dummy);
336 // ----------------------------------------------------------------------
337 // Day : Return the day of a date
339 // ----------------------------------------------------------------------
341 Standard_Integer Quantity_Date::Day(){
342 Standard_Integer dummy, day;
343 Values(dummy, day, dummy, dummy, dummy, dummy, dummy, dummy);
347 // ----------------------------------------------------------------------
348 // hour : Return the hour of a date
350 // ----------------------------------------------------------------------
352 Standard_Integer Quantity_Date::Hour(){
353 Standard_Integer dummy, hour;
354 Values(dummy, dummy, dummy, hour, dummy, dummy, dummy, dummy);
358 // ----------------------------------------------------------------------
359 // Minute : Return the minute of a date
361 // ----------------------------------------------------------------------
363 Standard_Integer Quantity_Date::Minute(){
364 Standard_Integer dummy, min;
365 Values(dummy, dummy, dummy, dummy, min, dummy, dummy, dummy);
369 // ----------------------------------------------------------------------
370 // Second : Return the second of a date
372 // ----------------------------------------------------------------------
374 Standard_Integer Quantity_Date::Second(){
375 Standard_Integer dummy, sec;
376 Values(dummy, dummy, dummy, dummy, dummy, sec , dummy, dummy);
380 // ----------------------------------------------------------------------
381 // millisecond : Return the millisecond of a date
383 // ----------------------------------------------------------------------
385 Standard_Integer Quantity_Date::MilliSecond(){
386 Standard_Integer dummy, msec;
387 Values(dummy, dummy, dummy, dummy, dummy, dummy, msec, dummy);
391 // ----------------------------------------------------------------------
392 // Day : Return the day of a date
394 // ----------------------------------------------------------------------
396 Standard_Integer Quantity_Date::MicroSecond(){
397 Standard_Integer dummy, msec;
398 Values(dummy, dummy, dummy, dummy, dummy, dummy, dummy, msec);
402 // ----------------------------------------------------------------------
403 // IsEarlier : Return true if the date is earlier than an other date
405 // ----------------------------------------------------------------------
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);
413 // ----------------------------------------------------------------------
414 // IsLater : Return true if the date is later than an other date
416 // ----------------------------------------------------------------------
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);
425 // ----------------------------------------------------------------------
426 // IsEqual : Return true if the date is the same than an other date
428 // ----------------------------------------------------------------------
430 Standard_Boolean Quantity_Date::IsEqual(const Quantity_Date& other)const{
431 return ( ( myUSec == other.myUSec &&
432 mySec == other.mySec ) ? Standard_True : Standard_False);