/* $Id $ */ /** @file * IPRT - Local Time, Posix. */ /* * Copyright (C) 2006-2007 Sun Microsystems, Inc. * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. * * The contents of this file may alternatively be used under the terms * of the Common Development and Distribution License Version 1.0 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the * VirtualBox OSE distribution, in which case the provisions of the * CDDL are applicable instead of those of the GPL. * * You may elect to license modified versions of this file under the * terms and conditions of either the GPL or the CDDL or both. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 USA or visit http://www.sun.com if you need * additional information or have any questions. */ /******************************************************************************* * Header Files * *******************************************************************************/ #define LOG_GROUP RTLOGGROUP_TIME #define RTTIME_INCL_TIMEVAL #include #include #include #include /** * This tries to find the UTC offset for a given timespec. * * It does probably not take into account changes in daylight * saving over the years or similar stuff. * * @returns UTC offset in nanoseconds. * @param pTime The time. * @param fCurrentTime Whether the input is current time or not. * This is for avoid infinit recursion on errors in the fallback path. */ static int64_t rtTimeLocalUTCOffset(PCRTTIMESPEC pTime, bool fCurrentTime) { RTTIMESPEC Fallback; /* * Convert to time_t. */ int64_t i64UnixTime = RTTimeSpecGetSeconds(pTime); time_t UnixTime = i64UnixTime; if (UnixTime != i64UnixTime) return fCurrentTime ? 0 : rtTimeLocalUTCOffset(RTTimeNow(&Fallback), true); /* * Explode it as both local and uct time. */ struct tm TmLocal; if ( !localtime_r(&UnixTime, &TmLocal) || !TmLocal.tm_year) return fCurrentTime ? 0 : rtTimeLocalUTCOffset(RTTimeNow(&Fallback), true); struct tm TmUct; if (!gmtime_r(&UnixTime, &TmUct)) return fCurrentTime ? 0 : rtTimeLocalUTCOffset(RTTimeNow(&Fallback), true); /* * Calc the difference (if any). * We ASSUME that the difference is less that 24 hours. */ if ( TmLocal.tm_hour == TmUct.tm_hour && TmLocal.tm_min == TmUct.tm_min && TmLocal.tm_sec == TmUct.tm_sec && TmLocal.tm_mday == TmUct.tm_mday) return 0; int LocalSecs = TmLocal.tm_hour * 3600 + TmLocal.tm_min * 60 + TmLocal.tm_sec; int UctSecs = TmUct.tm_hour * 3600 + TmUct.tm_min * 60 + TmUct.tm_sec; if (TmLocal.tm_mday != TmUct.tm_mday) { if ( ( TmLocal.tm_mday > TmUct.tm_mday && TmUct.tm_mday != 1) || TmLocal.tm_mday == 1) LocalSecs += 24*60*60; else UctSecs += 24*60*60; } return (LocalSecs - UctSecs) * INT64_C(1000000000); } /** * Gets the delta between UTC and local time. * * @code * RTTIMESPEC LocalTime; * RTTimeSpecAddNano(RTTimeNow(&LocalTime), RTTimeLocalDeltaNano()); * @endcode * * @returns Returns the nanosecond delta between UTC and local time. */ RTDECL(int64_t) RTTimeLocalDeltaNano(void) { RTTIMESPEC Time; return rtTimeLocalUTCOffset(RTTimeNow(&Time), true /* current time, skip fallback */); } /** * Explodes a time spec to the localized timezone. * * @returns pTime. * @param pTime Where to store the exploded time. * @param pTimeSpec The time spec to exploded. (UTC) */ RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec) { RTTIMESPEC LocalTime = *pTimeSpec; RTTimeSpecAddNano(&LocalTime, rtTimeLocalUTCOffset(&LocalTime, true /* current time, skip fallback */)); pTime = RTTimeExplode(pTime, &LocalTime); if (pTime) pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL; return pTime; }