diff options
Diffstat (limited to 'sal/osl/unx/time.cxx')
-rw-r--r-- | sal/osl/unx/time.cxx | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/sal/osl/unx/time.cxx b/sal/osl/unx/time.cxx new file mode 100644 index 0000000000..cf5473ff24 --- /dev/null +++ b/sal/osl/unx/time.cxx @@ -0,0 +1,311 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include "saltime.hxx" + +#include <osl/time.h> +#include <time.h> +#include <unistd.h> + +#ifdef __MACH__ +#include <mach/clock.h> +#include <mach/mach.h> +#endif + +/* FIXME: detection should be done in configure script */ +#if defined(MACOSX) || defined(IOS) || defined(FREEBSD) || defined(NETBSD) || \ + defined(LINUX) || defined(OPENBSD) || defined(DRAGONFLY) +#define STRUCT_TM_HAS_GMTOFF 1 + +#elif defined(__sun) +#define HAS_ALTZONE 1 +#endif + +#ifdef __MACH__ +typedef mach_timespec_t osl_time_t; +#else +#if defined(_POSIX_TIMERS) +#define USE_CLOCK_GETTIME +typedef struct timespec osl_time_t; +#else +typedef struct timeval osl_time_t; +#endif +#endif +static osl_time_t startTime; + +sal_Bool SAL_CALL osl_getSystemTime(TimeValue* tv) +{ +#ifdef __MACH__ + clock_serv_t cclock; + mach_timespec_t mts; + + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + + tv->Seconds = mts.tv_sec; + tv->Nanosec = mts.tv_nsec; +#else + int res; + osl_time_t tp; +#if defined(USE_CLOCK_GETTIME) + res = clock_gettime(CLOCK_REALTIME, &tp); +#else + res = gettimeofday(&tp, NULL); +#endif + + if (res != 0) + { + return false; + } + + tv->Seconds = tp.tv_sec; + #if defined(USE_CLOCK_GETTIME) + tv->Nanosec = tp.tv_nsec; + #else + tv->Nanosec = tp.tv_usec * 1000; + #endif +#endif + return true; +} + +sal_Bool SAL_CALL osl_getDateTimeFromTimeValue( const TimeValue* pTimeVal, oslDateTime* pDateTime ) +{ + struct tm *pSystemTime; + struct tm tmBuf; + time_t atime; + + atime = static_cast<time_t>(pTimeVal->Seconds); + + /* Convert time from type time_t to struct tm */ + pSystemTime = gmtime_r( &atime, &tmBuf ); + + /* Convert struct tm to struct oslDateTime */ + if ( pSystemTime != nullptr ) + { + pDateTime->NanoSeconds = pTimeVal->Nanosec; + pDateTime->Seconds = pSystemTime->tm_sec; + pDateTime->Minutes = pSystemTime->tm_min; + pDateTime->Hours = pSystemTime->tm_hour; + pDateTime->Day = pSystemTime->tm_mday; + pDateTime->DayOfWeek = pSystemTime->tm_wday; + pDateTime->Month = pSystemTime->tm_mon + 1; + pDateTime->Year = pSystemTime->tm_year + 1900; + + return true; + } + + return false; +} + +sal_Bool SAL_CALL osl_getTimeValueFromDateTime( const oslDateTime* pDateTime, TimeValue* pTimeVal ) +{ + struct tm aTime; + time_t nSeconds; + + /* Convert struct oslDateTime to struct tm */ + aTime.tm_sec = pDateTime->Seconds; + aTime.tm_min = pDateTime->Minutes; + aTime.tm_hour = pDateTime->Hours; + aTime.tm_mday = pDateTime->Day; + + if ( pDateTime->Month > 0 ) + aTime.tm_mon = pDateTime->Month - 1; + else + return false; + + aTime.tm_year = pDateTime->Year - 1900; + + aTime.tm_isdst = -1; + aTime.tm_wday = 0; + aTime.tm_yday = 0; + +#if defined(STRUCT_TM_HAS_GMTOFF) + aTime.tm_gmtoff = 0; +#endif + + /* Convert time to calendar value */ + nSeconds = mktime( &aTime ); + + /* + * mktime expects the struct tm to be in local timezone, so we have to adjust + * the returned value to be timezone neutral. + */ + + if ( nSeconds != time_t(-1) ) + { + time_t bias; + + /* timezone corrections */ + tzset(); + +#if defined(STRUCT_TM_HAS_GMTOFF) + /* members of struct tm are corrected by mktime */ + bias = 0 - aTime.tm_gmtoff; + +#elif defined(HAS_ALTZONE) + /* check if daylight saving time is in effect */ + bias = aTime.tm_isdst > 0 ? altzone : timezone; +#else + /* expect daylight saving time to be one hour */ + bias = aTime.tm_isdst > 0 ? timezone - 3600 : timezone; +#endif + + // coverity[store_truncates_time_t] - TODO: sal_uInt32 TimeValue::Seconds is only large + // enough for integer time_t values < 2^32 representing dates until year 2106: + pTimeVal->Seconds = nSeconds; + pTimeVal->Nanosec = pDateTime->NanoSeconds; + + if ( nSeconds > bias ) + pTimeVal->Seconds -= bias; + + return true; + } + + return false; +} + +sal_Bool SAL_CALL osl_getLocalTimeFromSystemTime( const TimeValue* pSystemTimeVal, TimeValue* pLocalTimeVal ) +{ + struct tm *pLocalTime; + struct tm tmBuf; + time_t bias; + time_t atime; + + atime = static_cast<time_t>(pSystemTimeVal->Seconds); + pLocalTime = localtime_r( &atime, &tmBuf ); + +#if defined(STRUCT_TM_HAS_GMTOFF) + /* members of struct tm are corrected by mktime */ + bias = -pLocalTime->tm_gmtoff; + +#elif defined(HAS_ALTZONE) + /* check if daylight saving time is in effect */ + bias = pLocalTime->tm_isdst > 0 ? altzone : timezone; +#else + /* expect daylight saving time to be one hour */ + bias = pLocalTime->tm_isdst > 0 ? timezone - 3600 : timezone; +#endif + + if ( static_cast<sal_Int64>(pSystemTimeVal->Seconds) > bias ) + { + pLocalTimeVal->Seconds = pSystemTimeVal->Seconds - bias; + pLocalTimeVal->Nanosec = pSystemTimeVal->Nanosec; + + return true; + } + + return false; +} + +sal_Bool SAL_CALL osl_getSystemTimeFromLocalTime( const TimeValue* pLocalTimeVal, TimeValue* pSystemTimeVal ) +{ + struct tm *pLocalTime; + struct tm tmBuf; + time_t bias; + time_t atime; + + atime = static_cast<time_t>(pLocalTimeVal->Seconds); + + /* Convert atime, which is a local time, to its GMT equivalent. Then, get + * the timezone offset for the local time for the GMT equivalent time. Note + * that we cannot directly use local time to determine the timezone offset + * because GMT is the only reliable time that we can determine timezone + * offset from. + */ + + atime = mktime( gmtime_r( &atime, &tmBuf ) ); + pLocalTime = localtime_r( &atime, &tmBuf ); + +#if defined(STRUCT_TM_HAS_GMTOFF) + /* members of struct tm are corrected by mktime */ + bias = 0 - pLocalTime->tm_gmtoff; + +#elif defined(HAS_ALTZONE) + /* check if daylight saving time is in effect */ + bias = pLocalTime->tm_isdst > 0 ? altzone : timezone; +#else + /* expect daylight saving time to be one hour */ + bias = pLocalTime->tm_isdst > 0 ? timezone - 3600 : timezone; +#endif + + if ( static_cast<sal_Int64>(pLocalTimeVal->Seconds) + bias > 0 ) + { + pSystemTimeVal->Seconds = pLocalTimeVal->Seconds + bias; + pSystemTimeVal->Nanosec = pLocalTimeVal->Nanosec; + + return true; + } + + return false; +} + +void sal_initGlobalTimer() +{ +#ifdef __MACH__ + clock_serv_t cclock; + + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); + clock_get_time(cclock, &startTime); + mach_port_deallocate(mach_task_self(), cclock); +#else /* ! (MACOSX || IOS) */ +#if defined(USE_CLOCK_GETTIME) + clock_gettime(CLOCK_REALTIME, &startTime); +#else /* Ndef USE_CLOCK_GETTIME */ + gettimeofday( &startTime, NULL ); +#endif /* NDef USE_CLOCK_GETTIME */ +#endif /* ! (MACOSX || IOS) */ +} + +sal_uInt32 SAL_CALL osl_getGlobalTimer() +{ + sal_uInt32 nSeconds; + +#ifdef __MACH__ + clock_serv_t cclock; + mach_timespec_t currentTime; + + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); + clock_get_time(cclock, ¤tTime); + mach_port_deallocate(mach_task_self(), cclock); + + nSeconds = ( currentTime.tv_sec - startTime.tv_sec ); + nSeconds = ( nSeconds * 1000 ) + static_cast<long>(( currentTime.tv_nsec - startTime.tv_nsec) / 1000000 ); +#else + osl_time_t currentTime; + +#if defined(USE_CLOCK_GETTIME) + clock_gettime(CLOCK_REALTIME, ¤tTime); +#else + gettimeofday( ¤tTime, NULL ); +#endif + + nSeconds = static_cast<sal_uInt32>( currentTime.tv_sec - startTime.tv_sec ); +#if defined(USE_CLOCK_GETTIME) + nSeconds = ( nSeconds * 1000 ) + static_cast<long>(( currentTime.tv_nsec - startTime.tv_nsec) / 1000000 ); +#else + nSeconds = ( nSeconds * 1000 ) + (long) (( currentTime.tv_usec - startTime.tv_usec) / 1000 ); +#endif +#endif + return nSeconds; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |