LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/tools/source/datetime - tdate.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 158 242 65.3 %
Date: 2013-07-09 Functions: 24 28 85.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #if defined( WNT )
      21             : #include <windows.h>
      22             : #else
      23             : #include <time.h>
      24             : #endif
      25             : 
      26             : #include <tools/date.hxx>
      27             : #include <sal/log.hxx>
      28             : 
      29             : #ifdef  MACOSX
      30             : extern "C" {
      31             : struct tm *localtime_r(const time_t *timep, struct tm *buffer);
      32             : }
      33             : #endif
      34             : 
      35             : static sal_uInt16 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30,
      36             :                                        31, 31, 30, 31, 30, 31 };
      37             : 
      38             : #define MAX_DAYS    3636532
      39             : 
      40       30072 : inline bool ImpIsLeapYear( sal_uInt16 nYear )
      41             : {
      42       59881 :     return ( ( ((nYear % 4) == 0) && ((nYear % 100) != 0) ) ||
      43       59881 :              ( (nYear % 400) == 0 ) );
      44             : }
      45             : 
      46             : // All callers must have sanitized or normalized month and year values!
      47      302043 : inline sal_uInt16 ImplDaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear )
      48             : {
      49      302043 :     if ( nMonth != 2 )
      50      271971 :         return aDaysInMonth[nMonth-1];
      51             :     else
      52             :     {
      53       30072 :         if (ImpIsLeapYear(nYear))
      54         281 :             return aDaysInMonth[nMonth-1] + 1;
      55             :         else
      56       29791 :             return aDaysInMonth[nMonth-1];
      57             :     }
      58             : }
      59             : 
      60             : // static
      61           4 : sal_uInt16 Date::GetDaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear )
      62             : {
      63             :     SAL_WARN_IF( nMonth < 1 || 12 < nMonth, "tools", "Date::GetDaysInMonth - nMonth out of bounds " << nMonth);
      64           4 :     if (nMonth < 1)
      65           0 :         nMonth = 1;
      66           4 :     else if (12 < nMonth)
      67           4 :         nMonth = 12;
      68           4 :     return ImplDaysInMonth( nMonth, nYear);
      69             : }
      70             : 
      71       23572 : long Date::DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear )
      72             : {
      73             :     long nDays;
      74             : 
      75       23572 :     Normalize( nDay, nMonth, nYear);
      76             : 
      77       23572 :     nDays = ((sal_uIntPtr)nYear-1) * 365;
      78       23572 :     nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400);
      79      206233 :     for( sal_uInt16 i = 1; i < nMonth; i++ )
      80      182661 :         nDays += ImplDaysInMonth(i,nYear);
      81       23572 :     nDays += nDay;
      82       23572 :     return nDays;
      83             : }
      84             : 
      85       10119 : static void DaysToDate( long nDays,
      86             :                         sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear )
      87             : {
      88             :     long    nTempDays;
      89       10119 :     long    i = 0;
      90             :     bool    bCalc;
      91             : 
      92       11700 :     do
      93             :     {
      94       11700 :         nTempDays = (long)nDays;
      95       11700 :         rYear = (sal_uInt16)((nTempDays / 365) - i);
      96       11700 :         nTempDays -= ((sal_uIntPtr)rYear-1) * 365;
      97       11700 :         nTempDays -= ((rYear-1) / 4) - ((rYear-1) / 100) + ((rYear-1) / 400);
      98       11700 :         bCalc = false;
      99       11700 :         if ( nTempDays < 1 )
     100             :         {
     101        1581 :             i++;
     102        1581 :             bCalc = true;
     103             :         }
     104             :         else
     105             :         {
     106       10119 :             if ( nTempDays > 365 )
     107             :             {
     108           0 :                 if ( (nTempDays != 366) || !ImpIsLeapYear( rYear ) )
     109             :                 {
     110           0 :                     i--;
     111           0 :                     bCalc = true;
     112             :                 }
     113             :             }
     114             :         }
     115             :     }
     116             :     while ( bCalc );
     117             : 
     118       10119 :     rMonth = 1;
     119       61426 :     while ( (sal_uIntPtr)nTempDays > ImplDaysInMonth( rMonth, rYear ) )
     120             :     {
     121       41188 :         nTempDays -= ImplDaysInMonth( rMonth, rYear );
     122       41188 :         rMonth++;
     123             :     }
     124       10119 :     rDay = (sal_uInt16)nTempDays;
     125       10119 : }
     126             : 
     127        7363 : Date::Date( DateInitSystem )
     128             : {
     129             : #if defined WNT
     130             :     SYSTEMTIME aDateTime;
     131             :     GetLocalTime( &aDateTime );
     132             : 
     133             :     // Combine to date
     134             :     nDate = ((sal_uIntPtr)aDateTime.wDay) +
     135             :             (((sal_uIntPtr)aDateTime.wMonth)*100) +
     136             :             (((sal_uIntPtr)aDateTime.wYear)*10000);
     137             : #else
     138             :     time_t     nTmpTime;
     139             :     struct tm aTime;
     140             : 
     141             :     // get current time
     142        7363 :     nTmpTime = time( 0 );
     143             : 
     144             :     // compute date
     145        7363 :     if ( localtime_r( &nTmpTime, &aTime ) )
     146             :     {
     147             :         nDate = ((sal_uIntPtr)aTime.tm_mday) +
     148       22089 :                 (((sal_uIntPtr)(aTime.tm_mon+1))*100) +
     149       22089 :                 (((sal_uIntPtr)(aTime.tm_year+1900))*10000);
     150             :     }
     151             :     else
     152           0 :         nDate = 1 + 100 + (((sal_uIntPtr)1900)*10000);
     153             : #endif
     154        7363 : }
     155             : 
     156          18 : void Date::SetDay( sal_uInt16 nNewDay )
     157             : {
     158          18 :     sal_uIntPtr  nMonth  = GetMonth();
     159          18 :     sal_uIntPtr  nYear   = GetYear();
     160             : 
     161          18 :     nDate = ((sal_uIntPtr)(nNewDay%100)) + (nMonth*100) + (nYear*10000);
     162          18 : }
     163             : 
     164          14 : void Date::SetMonth( sal_uInt16 nNewMonth )
     165             : {
     166          14 :     sal_uIntPtr  nDay    = GetDay();
     167          14 :     sal_uIntPtr  nYear   = GetYear();
     168             : 
     169          14 :     nDate = nDay + (((sal_uIntPtr)(nNewMonth%100))*100) + (nYear*10000);
     170          14 : }
     171             : 
     172         218 : void Date::SetYear( sal_uInt16 nNewYear )
     173             : {
     174         218 :     sal_uIntPtr  nDay   = GetDay();
     175         218 :     sal_uIntPtr  nMonth = GetMonth();
     176             : 
     177         218 :     nDate = nDay + (nMonth*100) + (((sal_uIntPtr)(nNewYear%10000))*10000);
     178         218 : }
     179             : 
     180          15 : DayOfWeek Date::GetDayOfWeek() const
     181             : {
     182          15 :     return (DayOfWeek)((sal_uIntPtr)(DateToDays( GetDay(), GetMonth(), GetYear() )-1) % 7);
     183             : }
     184             : 
     185          44 : sal_uInt16 Date::GetDayOfYear() const
     186             : {
     187          44 :     sal_uInt16 nDay   = GetDay();
     188          44 :     sal_uInt16 nMonth = GetMonth();
     189          44 :     sal_uInt16 nYear  = GetYear();
     190          44 :     Normalize( nDay, nMonth, nYear);
     191             : 
     192         151 :     for( sal_uInt16 i = 1; i < nMonth; i++ )
     193         107 :          nDay = nDay + ::ImplDaysInMonth( i, nYear );   // += yields a warning on MSVC, so don't use it
     194          44 :     return nDay;
     195             : }
     196             : 
     197           0 : sal_uInt16 Date::GetWeekOfYear( DayOfWeek eStartDay,
     198             :                             sal_Int16 nMinimumNumberOfDaysInWeek ) const
     199             : {
     200             :     short nWeek;
     201           0 :     short n1WDay = (short)Date( 1, 1, GetYear() ).GetDayOfWeek();
     202           0 :     short nDayOfYear = (short)GetDayOfYear();
     203             : 
     204             :     // weekdays start at 0, thus decrement one
     205           0 :     nDayOfYear--;
     206             :     // account for StartDay
     207           0 :     n1WDay = (n1WDay+(7-(short)eStartDay)) % 7;
     208             : 
     209           0 :     if (nMinimumNumberOfDaysInWeek < 1 || 7 < nMinimumNumberOfDaysInWeek)
     210             :     {
     211             :         SAL_WARN( "tools.datetime", "Date::GetWeekOfYear: invalid nMinimumNumberOfDaysInWeek" );
     212           0 :         nMinimumNumberOfDaysInWeek = 4;
     213             :     }
     214             : 
     215           0 :     if ( nMinimumNumberOfDaysInWeek == 1 )
     216             :     {
     217           0 :         nWeek = ((n1WDay+nDayOfYear)/7) + 1;
     218             :         // Set to 53rd week only if we're not in the
     219             :         // first week of the new year
     220           0 :         if ( nWeek == 54 )
     221           0 :             nWeek = 1;
     222           0 :         else if ( nWeek == 53 )
     223             :         {
     224           0 :             short nDaysInYear = (short)GetDaysInYear();
     225           0 :             short nDaysNextYear = (short)Date( 1, 1, GetYear()+1 ).GetDayOfWeek();
     226           0 :             nDaysNextYear = (nDaysNextYear+(7-(short)eStartDay)) % 7;
     227           0 :             if ( nDayOfYear > (nDaysInYear-nDaysNextYear-1) )
     228           0 :                 nWeek = 1;
     229             :         }
     230             :     }
     231           0 :     else if ( nMinimumNumberOfDaysInWeek == 7 )
     232             :     {
     233           0 :         nWeek = ((n1WDay+nDayOfYear)/7);
     234             :         // First week of a year is equal to the last week of the previous year
     235           0 :         if ( nWeek == 0 )
     236             :         {
     237           0 :             Date aLastDatePrevYear( 31, 12, GetYear()-1 );
     238           0 :             nWeek = aLastDatePrevYear.GetWeekOfYear( eStartDay, nMinimumNumberOfDaysInWeek );
     239             :         }
     240             :     }
     241             :     else // ( nMinimumNumberOfDaysInWeek == somehing_else, commentary examples for 4 )
     242             :     {
     243             :         // x_monday - thursday
     244           0 :         if ( n1WDay < nMinimumNumberOfDaysInWeek )
     245           0 :             nWeek = 1;
     246             :         // Friday
     247           0 :         else if ( n1WDay == nMinimumNumberOfDaysInWeek )
     248           0 :             nWeek = 53;
     249             :         // Saturday
     250           0 :         else if ( n1WDay == nMinimumNumberOfDaysInWeek + 1 )
     251             :         {
     252             :             // Year after leapyear
     253           0 :             if ( Date( 1, 1, GetYear()-1 ).IsLeapYear() )
     254           0 :                 nWeek = 53;
     255             :             else
     256           0 :                 nWeek = 52;
     257             :         }
     258             :         // Sunday
     259             :         else
     260           0 :             nWeek = 52;
     261             : 
     262           0 :         if ( (nWeek == 1) || (nDayOfYear + n1WDay > 6) )
     263             :         {
     264           0 :             if ( nWeek == 1 )
     265           0 :                 nWeek += (nDayOfYear + n1WDay) / 7;
     266             :             else
     267           0 :                 nWeek = (nDayOfYear + n1WDay) / 7;
     268           0 :             if ( nWeek == 53 )
     269             :             {
     270             :                 // next x_Sunday == first x_Sunday in the new year
     271             :                 // == still the same week!
     272           0 :                 long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
     273           0 :                 nTempDays +=  6 - (GetDayOfWeek()+(7-(short)eStartDay)) % 7;
     274             :                 sal_uInt16  nDay;
     275             :                 sal_uInt16  nMonth;
     276             :                 sal_uInt16  nYear;
     277           0 :                 DaysToDate( nTempDays, nDay, nMonth, nYear );
     278           0 :                 nWeek = Date( nDay, nMonth, nYear ).GetWeekOfYear( eStartDay, nMinimumNumberOfDaysInWeek );
     279             :             }
     280             :         }
     281             :     }
     282             : 
     283           0 :     return (sal_uInt16)nWeek;
     284             : }
     285             : 
     286        1376 : sal_uInt16 Date::GetDaysInMonth() const
     287             : {
     288        1376 :     sal_uInt16 nDay   = GetDay();
     289        1376 :     sal_uInt16 nMonth = GetMonth();
     290        1376 :     sal_uInt16 nYear  = GetYear();
     291        1376 :     Normalize( nDay, nMonth, nYear);
     292             : 
     293        1376 :     return ImplDaysInMonth( nMonth, nYear );
     294             : }
     295             : 
     296           0 : bool Date::IsLeapYear() const
     297             : {
     298           0 :     sal_uInt16 nYear = GetYear();
     299           0 :     return ImpIsLeapYear( nYear );
     300             : }
     301             : 
     302          63 : bool Date::IsValidAndGregorian() const
     303             : {
     304          63 :     sal_uInt16 nDay   = GetDay();
     305          63 :     sal_uInt16 nMonth = GetMonth();
     306          63 :     sal_uInt16 nYear  = GetYear();
     307             : 
     308          63 :     if ( !nMonth || (nMonth > 12) )
     309           3 :         return false;
     310          60 :     if ( !nDay || (nDay > ImplDaysInMonth( nMonth, nYear )) )
     311           0 :         return false;
     312          60 :     else if ( nYear <= 1582 )
     313             :     {
     314           0 :         if ( nYear < 1582 )
     315           0 :             return false;
     316           0 :         else if ( nMonth < 10 )
     317           0 :             return false;
     318           0 :         else if ( (nMonth == 10) && (nDay < 15) )
     319           0 :             return false;
     320             :     }
     321             : 
     322          60 :     return true;
     323             : }
     324             : 
     325         332 : bool Date::IsValidDate() const
     326             : {
     327         332 :     return IsValidDate( GetDay(), GetMonth(), GetYear());
     328             : }
     329             : 
     330             : //static
     331       25328 : bool Date::IsValidDate( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear )
     332             : {
     333       25328 :     if ( !nMonth || (nMonth > 12) )
     334          25 :         return false;
     335       25303 :     if ( !nDay || (nDay > ImplDaysInMonth( nMonth, nYear )) )
     336           0 :         return false;
     337       25303 :     return true;
     338             : }
     339             : 
     340           4 : bool Date::Normalize()
     341             : {
     342           4 :     sal_uInt16 nDay   = GetDay();
     343           4 :     sal_uInt16 nMonth = GetMonth();
     344           4 :     sal_uInt16 nYear  = GetYear();
     345             : 
     346           4 :     if (!Normalize( nDay, nMonth, nYear))
     347           4 :         return false;
     348             : 
     349           0 :     SetDay( nDay);
     350           0 :     SetMonth( nMonth);
     351           0 :     SetYear( nYear);
     352             : 
     353           0 :     return true;
     354             : }
     355             : 
     356             : //static
     357       24996 : bool Date::Normalize( sal_uInt16 & rDay, sal_uInt16 & rMonth, sal_uInt16 & rYear )
     358             : {
     359       24996 :     if (IsValidDate( rDay, rMonth, rYear))
     360       24975 :         return false;
     361             : 
     362          21 :     if (rMonth > 12)
     363             :     {
     364          18 :         rYear += rMonth / 12;
     365          18 :         rMonth = rMonth % 12;
     366             :     }
     367          21 :     if (!rMonth)
     368             :     {
     369           3 :         if (!rYear)
     370             :         {
     371           3 :             rYear = 0;
     372           3 :             rMonth = 1;
     373           3 :             if (rDay > 31)
     374           0 :                 rDay -= 31;
     375             :             else
     376           3 :                 rDay = 1;
     377             :         }
     378             :         else
     379             :         {
     380           0 :             --rYear;
     381           0 :             rMonth = 12;
     382             :         }
     383             :     }
     384             :     sal_uInt16 nDays;
     385          58 :     while (rDay > (nDays = ImplDaysInMonth( rMonth, rYear)))
     386             :     {
     387          16 :         rDay -= nDays;
     388          16 :         if (rMonth < 12)
     389          16 :             ++rMonth;
     390             :         else
     391             :         {
     392           0 :             ++rYear;
     393           0 :             rMonth = 1;
     394             :         }
     395             :     }
     396          21 :     if (rYear > 9999)
     397             :     {
     398           0 :         rDay = 31;
     399           0 :         rMonth = 12;
     400           0 :         rYear = 9999;
     401             :     }
     402          21 :     return true;
     403             : }
     404             : 
     405       10097 : Date& Date::operator +=( long nDays )
     406             : {
     407             :     sal_uInt16  nDay;
     408             :     sal_uInt16  nMonth;
     409             :     sal_uInt16  nYear;
     410       10097 :     long    nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
     411             : 
     412       10097 :     nTempDays += nDays;
     413       10097 :     if ( nTempDays > MAX_DAYS )
     414           0 :         nDate = 31 + (12*100) + (((sal_uIntPtr)9999)*10000);
     415       10097 :     else if ( nTempDays <= 0 )
     416           0 :         nDate = 1 + 100;
     417             :     else
     418             :     {
     419       10097 :         DaysToDate( nTempDays, nDay, nMonth, nYear );
     420       10097 :         nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000);
     421             :     }
     422             : 
     423       10097 :     return *this;
     424             : }
     425             : 
     426           9 : Date& Date::operator -=( long nDays )
     427             : {
     428             :     sal_uInt16  nDay;
     429             :     sal_uInt16  nMonth;
     430             :     sal_uInt16  nYear;
     431           9 :     long    nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
     432             : 
     433           9 :     nTempDays -= nDays;
     434           9 :     if ( nTempDays > MAX_DAYS )
     435           0 :         nDate = 31 + (12*100) + (((sal_uIntPtr)9999)*10000);
     436           9 :     else if ( nTempDays <= 0 )
     437           0 :         nDate = 1 + 100;
     438             :     else
     439             :     {
     440           9 :         DaysToDate( nTempDays, nDay, nMonth, nYear );
     441           9 :         nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000);
     442             :     }
     443             : 
     444           9 :     return *this;
     445             : }
     446             : 
     447          13 : Date& Date::operator ++()
     448             : {
     449             :     sal_uInt16  nDay;
     450             :     sal_uInt16  nMonth;
     451             :     sal_uInt16  nYear;
     452          13 :     long    nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
     453             : 
     454          13 :     if ( nTempDays < MAX_DAYS )
     455             :     {
     456          13 :         nTempDays++;
     457          13 :         DaysToDate( nTempDays, nDay, nMonth, nYear );
     458          13 :         nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000);
     459             :     }
     460             : 
     461          13 :     return *this;
     462             : }
     463             : 
     464           0 : Date& Date::operator --()
     465             : {
     466             :     sal_uInt16  nDay;
     467             :     sal_uInt16  nMonth;
     468             :     sal_uInt16  nYear;
     469           0 :     long    nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
     470             : 
     471           0 :     if ( nTempDays > 1 )
     472             :     {
     473           0 :         nTempDays--;
     474           0 :         DaysToDate( nTempDays, nDay, nMonth, nYear );
     475           0 :         nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000);
     476             :     }
     477           0 :     return *this;
     478             : }
     479             : 
     480           2 : Date Date::operator ++( int )
     481             : {
     482           2 :     Date aOldDate = *this;
     483           2 :     Date::operator++();
     484           2 :     return aOldDate;
     485             : }
     486             : 
     487           0 : Date Date::operator --( int )
     488             : {
     489           0 :     Date aOldDate = *this;
     490           0 :     Date::operator--();
     491           0 :     return aOldDate;
     492             : }
     493             : 
     494        3934 : Date operator +( const Date& rDate, long nDays )
     495             : {
     496        3934 :     Date aDate( rDate );
     497        3934 :     aDate += nDays;
     498        3934 :     return aDate;
     499             : }
     500             : 
     501           9 : Date operator -( const Date& rDate, long nDays )
     502             : {
     503           9 :     Date aDate( rDate );
     504           9 :     aDate -= nDays;
     505           9 :     return aDate;
     506             : }
     507             : 
     508        6719 : long operator -( const Date& rDate1, const Date& rDate2 )
     509             : {
     510       13438 :     sal_uIntPtr  nTempDays1 = Date::DateToDays( rDate1.GetDay(), rDate1.GetMonth(),
     511       20157 :                                     rDate1.GetYear() );
     512       13438 :     sal_uIntPtr  nTempDays2 = Date::DateToDays( rDate2.GetDay(), rDate2.GetMonth(),
     513       20157 :                                     rDate2.GetYear() );
     514        6719 :     return nTempDays1 - nTempDays2;
     515             : }
     516             : 
     517             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10