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 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_tools.hxx" 26 27 #if defined( OS2 ) 28 #define INCL_DOSDATETIME 29 #include <svpm.h> 30 #elif defined( WNT ) 31 #ifdef _MSC_VER 32 #pragma warning (push,1) 33 #endif 34 #include <tools/svwin.h> 35 #ifdef _MSC_VER 36 #pragma warning (pop) 37 #endif 38 #else 39 #include <time.h> 40 #endif 41 42 #include <tools/debug.hxx> 43 #include <tools/date.hxx> 44 #ifdef MACOSX 45 extern "C" { 46 struct tm *localtime_r(const time_t *timep, struct tm *buffer); 47 } 48 #endif 49 50 // ======================================================================= 51 52 static sal_uInt16 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30, 53 31, 31, 30, 31, 30, 31 }; 54 55 #define MAX_DAYS 3636532 56 57 // ======================================================================= 58 59 inline sal_Bool ImpIsLeapYear( sal_uInt16 nYear ) 60 { 61 return ( 62 ( ((nYear % 4) == 0) && ((nYear % 100) != 0) ) || 63 ( (nYear % 400) == 0 ) 64 ); 65 } 66 67 // ----------------------------------------------------------------------- 68 69 inline sal_uInt16 DaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear ) 70 { 71 if ( nMonth != 2 ) 72 return aDaysInMonth[nMonth-1]; 73 else 74 { 75 if (ImpIsLeapYear(nYear)) 76 return aDaysInMonth[nMonth-1] + 1; 77 else 78 return aDaysInMonth[nMonth-1]; 79 } 80 } 81 82 // ----------------------------------------------------------------------- 83 84 long Date::DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ) 85 { 86 long nDays; 87 88 nDays = ((sal_uIntPtr)nYear-1) * 365; 89 nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400); 90 for( sal_uInt16 i = 1; i < nMonth; i++ ) 91 nDays += DaysInMonth(i,nYear); 92 nDays += nDay; 93 return nDays; 94 } 95 96 // ----------------------------------------------------------------------- 97 98 static void DaysToDate( long nDays, 99 sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear ) 100 { 101 long nTempDays; 102 long i = 0; 103 sal_Bool bCalc; 104 105 do 106 { 107 nTempDays = (long)nDays; 108 rYear = (sal_uInt16)((nTempDays / 365) - i); 109 nTempDays -= ((sal_uIntPtr)rYear-1) * 365; 110 nTempDays -= ((rYear-1) / 4) - ((rYear-1) / 100) + ((rYear-1) / 400); 111 bCalc = sal_False; 112 if ( nTempDays < 1 ) 113 { 114 i++; 115 bCalc = sal_True; 116 } 117 else 118 { 119 if ( nTempDays > 365 ) 120 { 121 if ( (nTempDays != 366) || !ImpIsLeapYear( rYear ) ) 122 { 123 i--; 124 bCalc = sal_True; 125 } 126 } 127 } 128 } 129 while ( bCalc ); 130 131 rMonth = 1; 132 while ( (sal_uIntPtr)nTempDays > DaysInMonth( rMonth, rYear ) ) 133 { 134 nTempDays -= DaysInMonth( rMonth, rYear ); 135 rMonth++; 136 } 137 rDay = (sal_uInt16)nTempDays; 138 } 139 140 // ======================================================================= 141 142 Date::Date() 143 { 144 #if defined( OS2 ) 145 DATETIME aDateTime; 146 DosGetDateTime( &aDateTime ); 147 148 // Datum zusammenbauen 149 nDate = ((sal_uIntPtr)aDateTime.day) + 150 (((sal_uIntPtr)aDateTime.month)*100) + 151 (((sal_uIntPtr)aDateTime.year)*10000); 152 #elif defined WNT 153 SYSTEMTIME aDateTime; 154 GetLocalTime( &aDateTime ); 155 156 // Datum zusammenbauen 157 nDate = ((sal_uIntPtr)aDateTime.wDay) + 158 (((sal_uIntPtr)aDateTime.wMonth)*100) + 159 (((sal_uIntPtr)aDateTime.wYear)*10000); 160 #else 161 time_t nTmpTime; 162 struct tm aTime; 163 164 // Zeit ermitteln 165 nTmpTime = time( 0 ); 166 167 // Datum zusammenbauen 168 if ( localtime_r( &nTmpTime, &aTime ) ) 169 { 170 nDate = ((sal_uIntPtr)aTime.tm_mday) + 171 (((sal_uIntPtr)(aTime.tm_mon+1))*100) + 172 (((sal_uIntPtr)(aTime.tm_year+1900))*10000); 173 } 174 else 175 nDate = 1 + 100 + (((sal_uIntPtr)1900)*10000); 176 #endif 177 } 178 179 // ----------------------------------------------------------------------- 180 181 void Date::SetDay( sal_uInt16 nNewDay ) 182 { 183 sal_uIntPtr nMonth = GetMonth(); 184 sal_uIntPtr nYear = GetYear(); 185 186 nDate = ((sal_uIntPtr)(nNewDay%100)) + (nMonth*100) + (nYear*10000); 187 } 188 189 // ----------------------------------------------------------------------- 190 191 void Date::SetMonth( sal_uInt16 nNewMonth ) 192 { 193 sal_uIntPtr nDay = GetDay(); 194 sal_uIntPtr nYear = GetYear(); 195 196 nDate = nDay + (((sal_uIntPtr)(nNewMonth%100))*100) + (nYear*10000); 197 } 198 199 // ----------------------------------------------------------------------- 200 201 void Date::SetYear( sal_uInt16 nNewYear ) 202 { 203 sal_uIntPtr nDay = GetDay(); 204 sal_uIntPtr nMonth = GetMonth(); 205 206 nDate = nDay + (nMonth*100) + (((sal_uIntPtr)(nNewYear%10000))*10000); 207 } 208 209 // ----------------------------------------------------------------------- 210 211 DayOfWeek Date::GetDayOfWeek() const 212 { 213 return (DayOfWeek)((sal_uIntPtr)(DateToDays( GetDay(), GetMonth(), GetYear() )-1) % 7); 214 } 215 216 // ----------------------------------------------------------------------- 217 218 sal_uInt16 Date::GetDayOfYear() const 219 { 220 sal_uInt16 nDay = GetDay(); 221 for( sal_uInt16 i = 1; i < GetMonth(); i++ ) 222 nDay = nDay + ::DaysInMonth( i, GetYear() ); // += yields a warning on MSVC, so don't use it 223 return nDay; 224 } 225 226 // ----------------------------------------------------------------------- 227 228 sal_uInt16 Date::GetWeekOfYear( DayOfWeek eStartDay, 229 sal_Int16 nMinimumNumberOfDaysInWeek ) const 230 { 231 short nWeek; 232 short n1WDay = (short)Date( 1, 1, GetYear() ).GetDayOfWeek(); 233 short nDayOfYear = (short)GetDayOfYear(); 234 235 // Wochentage beginnen bei 0, deshalb einen abziehen 236 nDayOfYear--; 237 // StartDay beruecksichtigen 238 n1WDay = (n1WDay+(7-(short)eStartDay)) % 7; 239 240 if (nMinimumNumberOfDaysInWeek < 1 || 7 < nMinimumNumberOfDaysInWeek) 241 { 242 DBG_ERRORFILE("Date::GetWeekOfYear: invalid nMinimumNumberOfDaysInWeek"); 243 nMinimumNumberOfDaysInWeek = 4; 244 } 245 246 if ( nMinimumNumberOfDaysInWeek == 1 ) 247 { 248 nWeek = ((n1WDay+nDayOfYear)/7) + 1; 249 // 53te-Woche nur dann, wenn wir nicht schon in der ersten 250 // Woche des neuen Jahres liegen 251 if ( nWeek == 54 ) 252 nWeek = 1; 253 else if ( nWeek == 53 ) 254 { 255 short nDaysInYear = (short)GetDaysInYear(); 256 short nDaysNextYear = (short)Date( 1, 1, GetYear()+1 ).GetDayOfWeek(); 257 nDaysNextYear = (nDaysNextYear+(7-(short)eStartDay)) % 7; 258 if ( nDayOfYear > (nDaysInYear-nDaysNextYear-1) ) 259 nWeek = 1; 260 } 261 } 262 else if ( nMinimumNumberOfDaysInWeek == 7 ) 263 { 264 nWeek = ((n1WDay+nDayOfYear)/7); 265 // Erste Woche eines Jahres entspricht der letzen Woche des 266 // vorherigen Jahres 267 if ( nWeek == 0 ) 268 { 269 Date aLastDatePrevYear( 31, 12, GetYear()-1 ); 270 nWeek = aLastDatePrevYear.GetWeekOfYear( eStartDay, nMinimumNumberOfDaysInWeek ); 271 } 272 } 273 else // ( nMinimumNumberOfDaysInWeek == somehing_else, commentary examples for 4 ) 274 { 275 // x_monday - thursday 276 if ( n1WDay < nMinimumNumberOfDaysInWeek ) 277 nWeek = 1; 278 // friday 279 else if ( n1WDay == nMinimumNumberOfDaysInWeek ) 280 nWeek = 53; 281 // saturday 282 else if ( n1WDay == nMinimumNumberOfDaysInWeek + 1 ) 283 { 284 // Jahr nach Schaltjahr 285 if ( Date( 1, 1, GetYear()-1 ).IsLeapYear() ) 286 nWeek = 53; 287 else 288 nWeek = 52; 289 } 290 // sunday 291 else 292 nWeek = 52; 293 294 if ( (nWeek == 1) || (nDayOfYear + n1WDay > 6) ) 295 { 296 if ( nWeek == 1 ) 297 nWeek += (nDayOfYear + n1WDay) / 7; 298 else 299 nWeek = (nDayOfYear + n1WDay) / 7; 300 if ( nWeek == 53 ) 301 { 302 // naechster x_Sonntag == erster x_Sonntag im neuen Jahr 303 // == noch gleiche Woche 304 long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() ); 305 nTempDays += 6 - (GetDayOfWeek()+(7-(short)eStartDay)) % 7; 306 sal_uInt16 nDay; 307 sal_uInt16 nMonth; 308 sal_uInt16 nYear; 309 DaysToDate( nTempDays, nDay, nMonth, nYear ); 310 nWeek = Date( nDay, nMonth, nYear ).GetWeekOfYear( eStartDay, nMinimumNumberOfDaysInWeek ); 311 } 312 } 313 } 314 315 return (sal_uInt16)nWeek; 316 } 317 318 // ----------------------------------------------------------------------- 319 320 sal_uInt16 Date::GetDaysInMonth() const 321 { 322 return DaysInMonth( GetMonth(), GetYear() ); 323 } 324 325 // ----------------------------------------------------------------------- 326 327 sal_Bool Date::IsLeapYear() const 328 { 329 sal_uInt16 nYear = GetYear(); 330 return ImpIsLeapYear( nYear ); 331 } 332 333 // ----------------------------------------------------------------------- 334 335 sal_Bool Date::IsValid() const 336 { 337 sal_uInt16 nDay = GetDay(); 338 sal_uInt16 nMonth = GetMonth(); 339 sal_uInt16 nYear = GetYear(); 340 341 if ( !nMonth || (nMonth > 12) ) 342 return sal_False; 343 if ( !nDay || (nDay > DaysInMonth( nMonth, nYear )) ) 344 return sal_False; 345 else if ( nYear <= 1582 ) 346 { 347 if ( nYear < 1582 ) 348 return sal_False; 349 else if ( nMonth < 10 ) 350 return sal_False; 351 else if ( (nMonth == 10) && (nDay < 15) ) 352 return sal_False; 353 } 354 355 return sal_True; 356 } 357 358 // ----------------------------------------------------------------------- 359 360 Date& Date::operator +=( long nDays ) 361 { 362 sal_uInt16 nDay; 363 sal_uInt16 nMonth; 364 sal_uInt16 nYear; 365 long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() ); 366 367 nTempDays += nDays; 368 if ( nTempDays > MAX_DAYS ) 369 nDate = 31 + (12*100) + (((sal_uIntPtr)9999)*10000); 370 else if ( nTempDays <= 0 ) 371 nDate = 1 + 100; 372 else 373 { 374 DaysToDate( nTempDays, nDay, nMonth, nYear ); 375 nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000); 376 } 377 378 return *this; 379 } 380 381 // ----------------------------------------------------------------------- 382 383 Date& Date::operator -=( long nDays ) 384 { 385 sal_uInt16 nDay; 386 sal_uInt16 nMonth; 387 sal_uInt16 nYear; 388 long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() ); 389 390 nTempDays -= nDays; 391 if ( nTempDays > MAX_DAYS ) 392 nDate = 31 + (12*100) + (((sal_uIntPtr)9999)*10000); 393 else if ( nTempDays <= 0 ) 394 nDate = 1 + 100; 395 else 396 { 397 DaysToDate( nTempDays, nDay, nMonth, nYear ); 398 nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000); 399 } 400 401 return *this; 402 } 403 404 // ----------------------------------------------------------------------- 405 406 Date& Date::operator ++() 407 { 408 sal_uInt16 nDay; 409 sal_uInt16 nMonth; 410 sal_uInt16 nYear; 411 long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() ); 412 413 if ( nTempDays < MAX_DAYS ) 414 { 415 nTempDays++; 416 DaysToDate( nTempDays, nDay, nMonth, nYear ); 417 nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000); 418 } 419 420 return *this; 421 } 422 423 // ----------------------------------------------------------------------- 424 425 Date& Date::operator --() 426 { 427 sal_uInt16 nDay; 428 sal_uInt16 nMonth; 429 sal_uInt16 nYear; 430 long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() ); 431 432 if ( nTempDays > 1 ) 433 { 434 nTempDays--; 435 DaysToDate( nTempDays, nDay, nMonth, nYear ); 436 nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000); 437 } 438 return *this; 439 } 440 441 #ifndef MPW33 442 443 // ----------------------------------------------------------------------- 444 445 Date Date::operator ++( int ) 446 { 447 Date aOldDate = *this; 448 Date::operator++(); 449 return aOldDate; 450 } 451 452 // ----------------------------------------------------------------------- 453 454 Date Date::operator --( int ) 455 { 456 Date aOldDate = *this; 457 Date::operator--(); 458 return aOldDate; 459 } 460 461 #endif 462 463 // ----------------------------------------------------------------------- 464 465 Date operator +( const Date& rDate, long nDays ) 466 { 467 Date aDate( rDate ); 468 aDate += nDays; 469 return aDate; 470 } 471 472 // ----------------------------------------------------------------------- 473 474 Date operator -( const Date& rDate, long nDays ) 475 { 476 Date aDate( rDate ); 477 aDate -= nDays; 478 return aDate; 479 } 480 481 // ----------------------------------------------------------------------- 482 483 long operator -( const Date& rDate1, const Date& rDate2 ) 484 { 485 sal_uIntPtr nTempDays1 = Date::DateToDays( rDate1.GetDay(), rDate1.GetMonth(), 486 rDate1.GetYear() ); 487 sal_uIntPtr nTempDays2 = Date::DateToDays( rDate2.GetDay(), rDate2.GetMonth(), 488 rDate2.GetYear() ); 489 return nTempDays1 - nTempDays2; 490 } 491