summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2017-05-05 22:56:13 +0200
committerEike Rathke <erack@redhat.com>2017-05-05 22:56:41 +0200
commit7a47058e41a6fc2fdf23673fd583ebc8ca0b5541 (patch)
tree43bfd83f4e48dfedfe8f9449b4c01fa697b32289 /tools
parente4da2e5dfa9e462e0d9c23a1a60caf4b3ef2dc56 (diff)
DateTime::CreateFromWin32FileDateTime: FILETIME is uint64
Called with a (stray value read from file?) sometimes absurdly high value treated as an int64 negative value which the algorithm couldn't cope with, resulting in weird DateTime ctor arguments that now assert. Changed to uint64 and replaced calculation with Date::operator+=(long) Change-Id: Ia8dbc10c4c633208730fce583e43afd828e7546f
Diffstat (limited to 'tools')
-rw-r--r--tools/source/datetime/datetime.cxx51
1 files changed, 21 insertions, 30 deletions
diff --git a/tools/source/datetime/datetime.cxx b/tools/source/datetime/datetime.cxx
index d24f6f818184..eedbdea51abb 100644
--- a/tools/source/datetime/datetime.cxx
+++ b/tools/source/datetime/datetime.cxx
@@ -244,42 +244,33 @@ void DateTime::GetWin32FileDateTime( sal_uInt32 & rLower, sal_uInt32 & rUpper )
DateTime DateTime::CreateFromWin32FileDateTime( sal_uInt32 rLower, sal_uInt32 rUpper )
{
- const sal_Int64 a100nPerSecond = SAL_CONST_INT64( 10000000 );
- const sal_Int64 a100nPerDay = a100nPerSecond * sal_Int64( 60 * 60 * 24 );
+ // (rUpper|rLower) = 100-nanosecond intervals since 1601-01-01 00:00
+ const sal_uInt64 a100nPerSecond = SAL_CONST_UINT64( 10000000 );
+ const sal_uInt64 a100nPerDay = a100nPerSecond * sal_uInt64( 60 * 60 * 24 );
- sal_Int64 aTime = sal_Int64(
+ sal_uInt64 aTime =
sal_uInt64( rUpper ) * SAL_CONST_UINT64( 0x100000000 ) +
- sal_uInt64( rLower ) );
+ sal_uInt64( rLower );
- sal_Int64 nDays = aTime / a100nPerDay;
- sal_Int64 nYears =
- ( nDays -
- ( nDays / ( 4 * 365 ) ) +
- ( nDays / ( 100 * 365 ) ) -
- ( nDays / ( 400 * 365 ) ) ) / 365;
- nDays -= nYears * 365 + nYears / 4 - nYears / 100 + nYears / 400;
+ SAL_WARN_IF( static_cast<sal_Int64>(aTime) < 0, "tools.datetime",
+ "DateTime::CreateFromWin32FileDateTime - absurdly high value expected?");
- sal_uInt16 nMonths = 0;
- for( sal_Int64 nDaysCount = nDays; nDaysCount >= 0; )
- {
- nDays = nDaysCount;
- nMonths ++;
- nDaysCount -= Date(
- 1, nMonths, sal::static_int_cast< sal_uInt16 >(1601 + nYears) ).
- GetDaysInMonth();
- }
+ sal_uInt64 nDays = aTime / a100nPerDay;
+
+ Date aDate(1,1,1601);
+ // (0xffffffffffffffff / a100nPerDay = 21350398) fits into long
+ // (0x7fffffff = 2147483647)
+ aDate += static_cast<long>(nDays);
- Date _aDate(
- (sal_uInt16)( nDays + 1 ), nMonths,
- sal::static_int_cast< sal_uInt16 >(nYears + 1601) );
- tools::Time _aTime(
- static_cast<sal_uInt32>( ( aTime / ( a100nPerSecond * 60 * 60 ) ) % sal_Int64( 24 ) ),
- static_cast<sal_uInt32>( ( aTime / ( a100nPerSecond * 60 ) ) % sal_Int64( 60 ) ),
- static_cast<sal_uInt32>( ( aTime / ( a100nPerSecond ) ) % sal_Int64( 60 ) ),
- static_cast<sal_uInt64>(aTime % a100nPerSecond) * 100
- );
+ SAL_WARN_IF( aDate - Date(1,1,1601) != static_cast<long>(nDays), "tools.datetime",
+ "DateTime::CreateFromWin32FileDateTime - date truncated to max");
- return DateTime( _aDate, _aTime );
+ sal_uInt64 nNanos = (aTime - (nDays * a100nPerDay)) * 100;
+ return DateTime( aDate, tools::Time(
+ static_cast<sal_uInt32>((nNanos / tools::Time::nanoSecPerHour) % sal_uInt64( 24 )),
+ static_cast<sal_uInt32>((nNanos / tools::Time::nanoSecPerMinute) % sal_uInt64( 60 )),
+ static_cast<sal_uInt32>((nNanos / tools::Time::nanoSecPerSec) % sal_uInt64( 60 )),
+ static_cast<sal_uInt64>( nNanos % tools::Time::nanoSecPerSec)));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */