LCOV - code coverage report
Current view: top level - tools/source/datetime - tdate.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 246 0.0 %
Date: 2014-04-14 Functions: 0 28 0.0 %
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 const 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           0 : inline bool ImpIsLeapYear( sal_uInt16 nYear )
      41             : {
      42           0 :     return ( ( ((nYear % 4) == 0) && ((nYear % 100) != 0) ) ||
      43           0 :              ( (nYear % 400) == 0 ) );
      44             : }
      45             : 
      46             : // All callers must have sanitized or normalized month and year values!
      47           0 : inline sal_uInt16 ImplDaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear )
      48             : {
      49           0 :     if ( nMonth != 2 )
      50           0 :         return aDaysInMonth[nMonth-1];
      51             :     else
      52             :     {
      53           0 :         if (ImpIsLeapYear(nYear))
      54           0 :             return aDaysInMonth[nMonth-1] + 1;
      55             :         else
      56           0 :             return aDaysInMonth[nMonth-1];
      57             :     }
      58             : }
      59             : 
      60             : // static
      61           0 : 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           0 :     if (nMonth < 1)
      65           0 :         nMonth = 1;
      66           0 :     else if (12 < nMonth)
      67           0 :         nMonth = 12;
      68           0 :     return ImplDaysInMonth( nMonth, nYear);
      69             : }
      70             : 
      71           0 : long Date::DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear )
      72             : {
      73             :     long nDays;
      74             : 
      75           0 :     Normalize( nDay, nMonth, nYear);
      76             : 
      77           0 :     nDays = ((sal_uIntPtr)nYear-1) * 365;
      78           0 :     nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400);
      79           0 :     for( sal_uInt16 i = 1; i < nMonth; i++ )
      80           0 :         nDays += ImplDaysInMonth(i,nYear);
      81           0 :     nDays += nDay;
      82           0 :     return nDays;
      83             : }
      84             : 
      85           0 : static void DaysToDate( long nDays,
      86             :                         sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear )
      87             : {
      88             :     long    nTempDays;
      89           0 :     long    i = 0;
      90             :     bool    bCalc;
      91             : 
      92           0 :     do
      93             :     {
      94           0 :         nTempDays = (long)nDays;
      95           0 :         rYear = (sal_uInt16)((nTempDays / 365) - i);
      96           0 :         nTempDays -= ((sal_uIntPtr)rYear-1) * 365;
      97           0 :         nTempDays -= ((rYear-1) / 4) - ((rYear-1) / 100) + ((rYear-1) / 400);
      98           0 :         bCalc = false;
      99           0 :         if ( nTempDays < 1 )
     100             :         {
     101           0 :             i++;
     102           0 :             bCalc = true;
     103             :         }
     104             :         else
     105             :         {
     106           0 :             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           0 :     rMonth = 1;
     119           0 :     while ( (sal_uIntPtr)nTempDays > ImplDaysInMonth( rMonth, rYear ) )
     120             :     {
     121           0 :         nTempDays -= ImplDaysInMonth( rMonth, rYear );
     122           0 :         rMonth++;
     123             :     }
     124           0 :     rDay = (sal_uInt16)nTempDays;
     125           0 : }
     126             : 
     127           0 : 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           0 :     nTmpTime = time( 0 );
     143             : 
     144             :     // compute date
     145           0 :     if ( localtime_r( &nTmpTime, &aTime ) )
     146             :     {
     147             :         nDate = ((sal_uIntPtr)aTime.tm_mday) +
     148           0 :                 (((sal_uIntPtr)(aTime.tm_mon+1))*100) +
     149           0 :                 (((sal_uIntPtr)(aTime.tm_year+1900))*10000);
     150             :     }
     151             :     else
     152           0 :         nDate = 1 + 100 + (((sal_uIntPtr)1900)*10000);
     153             : #endif
     154           0 : }
     155             : 
     156           0 : void Date::SetDay( sal_uInt16 nNewDay )
     157             : {
     158           0 :     sal_uIntPtr  nMonth  = GetMonth();
     159           0 :     sal_uIntPtr  nYear   = GetYear();
     160             : 
     161           0 :     nDate = ((sal_uIntPtr)(nNewDay%100)) + (nMonth*100) + (nYear*10000);
     162           0 : }
     163             : 
     164           0 : void Date::SetMonth( sal_uInt16 nNewMonth )
     165             : {
     166           0 :     sal_uIntPtr  nDay    = GetDay();
     167           0 :     sal_uIntPtr  nYear   = GetYear();
     168             : 
     169           0 :     nDate = nDay + (((sal_uIntPtr)(nNewMonth%100))*100) + (nYear*10000);
     170           0 : }
     171             : 
     172           0 : void Date::SetYear( sal_uInt16 nNewYear )
     173             : {
     174           0 :     sal_uIntPtr  nDay   = GetDay();
     175           0 :     sal_uIntPtr  nMonth = GetMonth();
     176             : 
     177           0 :     nDate = nDay + (nMonth*100) + (((sal_uIntPtr)(nNewYear%10000))*10000);
     178           0 : }
     179             : 
     180           0 : DayOfWeek Date::GetDayOfWeek() const
     181             : {
     182           0 :     return (DayOfWeek)((sal_uIntPtr)(DateToDays( GetDay(), GetMonth(), GetYear() )-1) % 7);
     183             : }
     184             : 
     185           0 : sal_uInt16 Date::GetDayOfYear() const
     186             : {
     187           0 :     sal_uInt16 nDay   = GetDay();
     188           0 :     sal_uInt16 nMonth = GetMonth();
     189           0 :     sal_uInt16 nYear  = GetYear();
     190           0 :     Normalize( nDay, nMonth, nYear);
     191             : 
     192           0 :     for( sal_uInt16 i = 1; i < nMonth; i++ )
     193           0 :          nDay = nDay + ::ImplDaysInMonth( i, nYear );   // += yields a warning on MSVC, so don't use it
     194           0 :     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           0 : sal_uInt16 Date::GetDaysInMonth() const
     287             : {
     288           0 :     sal_uInt16 nDay   = GetDay();
     289           0 :     sal_uInt16 nMonth = GetMonth();
     290           0 :     sal_uInt16 nYear  = GetYear();
     291           0 :     Normalize( nDay, nMonth, nYear);
     292             : 
     293           0 :     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           0 : bool Date::IsValidAndGregorian() const
     303             : {
     304           0 :     sal_uInt16 nDay   = GetDay();
     305           0 :     sal_uInt16 nMonth = GetMonth();
     306           0 :     sal_uInt16 nYear  = GetYear();
     307             : 
     308           0 :     if ( !nMonth || (nMonth > 12) )
     309           0 :         return false;
     310           0 :     if ( !nDay || (nDay > ImplDaysInMonth( nMonth, nYear )) )
     311           0 :         return false;
     312           0 :     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           0 :     return true;
     323             : }
     324             : 
     325           0 : bool Date::IsValidDate() const
     326             : {
     327           0 :     return IsValidDate( GetDay(), GetMonth(), GetYear());
     328             : }
     329             : 
     330             : //static
     331           0 : bool Date::IsValidDate( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear )
     332             : {
     333           0 :     if ( !nMonth || (nMonth > 12) )
     334           0 :         return false;
     335           0 :     if ( !nDay || (nDay > ImplDaysInMonth( nMonth, nYear )) )
     336           0 :         return false;
     337           0 :     return true;
     338             : }
     339             : 
     340           0 : bool Date::Normalize()
     341             : {
     342           0 :     sal_uInt16 nDay   = GetDay();
     343           0 :     sal_uInt16 nMonth = GetMonth();
     344           0 :     sal_uInt16 nYear  = GetYear();
     345             : 
     346           0 :     if (!Normalize( nDay, nMonth, nYear))
     347           0 :         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           0 : bool Date::Normalize( sal_uInt16 & rDay, sal_uInt16 & rMonth, sal_uInt16 & rYear )
     358             : {
     359           0 :     if (IsValidDate( rDay, rMonth, rYear))
     360           0 :         return false;
     361             : 
     362           0 :     if (rMonth > 12)
     363             :     {
     364           0 :         rYear += rMonth / 12;
     365           0 :         rMonth = rMonth % 12;
     366             :     }
     367           0 :     if (!rMonth)
     368             :     {
     369           0 :         if (!rYear)
     370             :         {
     371           0 :             rYear = 0;
     372           0 :             rMonth = 1;
     373           0 :             if (rDay > 31)
     374           0 :                 rDay -= 31;
     375             :             else
     376           0 :                 rDay = 1;
     377             :         }
     378             :         else
     379             :         {
     380           0 :             --rYear;
     381           0 :             rMonth = 12;
     382             :         }
     383             :     }
     384             :     sal_uInt16 nDays;
     385           0 :     while (rDay > (nDays = ImplDaysInMonth( rMonth, rYear)))
     386             :     {
     387           0 :         rDay -= nDays;
     388           0 :         if (rMonth < 12)
     389           0 :             ++rMonth;
     390             :         else
     391             :         {
     392           0 :             ++rYear;
     393           0 :             rMonth = 1;
     394             :         }
     395             :     }
     396           0 :     if (rYear > 9999)
     397             :     {
     398           0 :         rDay = 31;
     399           0 :         rMonth = 12;
     400           0 :         rYear = 9999;
     401             :     }
     402           0 :     return true;
     403             : }
     404             : 
     405           0 : Date& Date::operator +=( long nDays )
     406             : {
     407             :     sal_uInt16  nDay;
     408             :     sal_uInt16  nMonth;
     409             :     sal_uInt16  nYear;
     410             : 
     411           0 :     if (nDays == 0)
     412           0 :         return *this;
     413             : 
     414           0 :     long    nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
     415             : 
     416           0 :     nTempDays += nDays;
     417           0 :     if ( nTempDays > MAX_DAYS )
     418           0 :         nDate = 31 + (12*100) + (((sal_uIntPtr)9999)*10000);
     419           0 :     else if ( nTempDays <= 0 )
     420           0 :         nDate = 1 + 100;
     421             :     else
     422             :     {
     423           0 :         DaysToDate( nTempDays, nDay, nMonth, nYear );
     424           0 :         nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000);
     425             :     }
     426             : 
     427           0 :     return *this;
     428             : }
     429             : 
     430           0 : Date& Date::operator -=( long nDays )
     431             : {
     432             :     sal_uInt16  nDay;
     433             :     sal_uInt16  nMonth;
     434             :     sal_uInt16  nYear;
     435             : 
     436           0 :     if (nDays == 0)
     437           0 :         return *this;
     438             : 
     439           0 :     long    nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
     440             : 
     441           0 :     nTempDays -= nDays;
     442           0 :     if ( nTempDays > MAX_DAYS )
     443           0 :         nDate = 31 + (12*100) + (((sal_uIntPtr)9999)*10000);
     444           0 :     else if ( nTempDays <= 0 )
     445           0 :         nDate = 1 + 100;
     446             :     else
     447             :     {
     448           0 :         DaysToDate( nTempDays, nDay, nMonth, nYear );
     449           0 :         nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000);
     450             :     }
     451             : 
     452           0 :     return *this;
     453             : }
     454             : 
     455           0 : Date& Date::operator ++()
     456             : {
     457             :     sal_uInt16  nDay;
     458             :     sal_uInt16  nMonth;
     459             :     sal_uInt16  nYear;
     460           0 :     long    nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
     461             : 
     462           0 :     if ( nTempDays < MAX_DAYS )
     463             :     {
     464           0 :         nTempDays++;
     465           0 :         DaysToDate( nTempDays, nDay, nMonth, nYear );
     466           0 :         nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000);
     467             :     }
     468             : 
     469           0 :     return *this;
     470             : }
     471             : 
     472           0 : Date& Date::operator --()
     473             : {
     474             :     sal_uInt16  nDay;
     475             :     sal_uInt16  nMonth;
     476             :     sal_uInt16  nYear;
     477           0 :     long    nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() );
     478             : 
     479           0 :     if ( nTempDays > 1 )
     480             :     {
     481           0 :         nTempDays--;
     482           0 :         DaysToDate( nTempDays, nDay, nMonth, nYear );
     483           0 :         nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000);
     484             :     }
     485           0 :     return *this;
     486             : }
     487             : 
     488           0 : Date Date::operator ++( int )
     489             : {
     490           0 :     Date aOldDate = *this;
     491           0 :     Date::operator++();
     492           0 :     return aOldDate;
     493             : }
     494             : 
     495           0 : Date Date::operator --( int )
     496             : {
     497           0 :     Date aOldDate = *this;
     498           0 :     Date::operator--();
     499           0 :     return aOldDate;
     500             : }
     501             : 
     502           0 : Date operator +( const Date& rDate, long nDays )
     503             : {
     504           0 :     Date aDate( rDate );
     505           0 :     aDate += nDays;
     506           0 :     return aDate;
     507             : }
     508             : 
     509           0 : Date operator -( const Date& rDate, long nDays )
     510             : {
     511           0 :     Date aDate( rDate );
     512           0 :     aDate -= nDays;
     513           0 :     return aDate;
     514             : }
     515             : 
     516           0 : long operator -( const Date& rDate1, const Date& rDate2 )
     517             : {
     518           0 :     sal_uIntPtr  nTempDays1 = Date::DateToDays( rDate1.GetDay(), rDate1.GetMonth(),
     519           0 :                                     rDate1.GetYear() );
     520           0 :     sal_uIntPtr  nTempDays2 = Date::DateToDays( rDate2.GetDay(), rDate2.GetMonth(),
     521           0 :                                     rDate2.GetYear() );
     522           0 :     return nTempDays1 - nTempDays2;
     523             : }
     524             : 
     525             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10