1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/* Portions are Copyright (C) 2011 Google Inc */ 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* ***** BEGIN LICENSE BLOCK ***** 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The contents of this file are subject to the Mozilla Public License Version 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 1.1 (the "License"); you may not use this file except in compliance with 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the License. You may obtain a copy of the License at 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * http://www.mozilla.org/MPL/ 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Software distributed under the License is distributed on an "AS IS" basis, 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * for the specific language governing rights and limitations under the 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * License. 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The Original Code is the Netscape Portable Runtime (NSPR). 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The Initial Developer of the Original Code is 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Netscape Communications Corporation. 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Portions created by the Initial Developer are Copyright (C) 1998-2000 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the Initial Developer. All Rights Reserved. 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Contributor(s): 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Alternatively, the contents of this file may be used under the terms of 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * either the GNU General Public License Version 2 or later (the "GPL"), or 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * in which case the provisions of the GPL or the LGPL are applicable instead 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * of those above. If you wish to allow use of your version of this file only 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * under the terms of either the GPL or the LGPL, and not to allow others to 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * use your version of this file under the terms of the MPL, indicate your 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * decision by deleting the provisions above and replace them with the notice 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * and other provisions required by the GPL or the LGPL. If you do not delete 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the provisions above, a recipient may use your version of this file under 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the terms of any one of the MPL, the GPL or the LGPL. 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * ***** END LICENSE BLOCK ***** */ 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * prtime.cc -- 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * NOTE: The original nspr file name is prtime.c 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * NSPR date and time functions 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * CVS revision 3.37 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The following functions were copied from the NSPR prtime.c file. 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * PR_ParseTimeString 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * We inlined the new PR_ParseTimeStringToExplodedTime function to avoid 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * copying PR_ExplodeTime and PR_LocalTimeParameters. (The PR_ExplodeTime 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * and PR_ImplodeTime calls cancel each other out.) 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * PR_NormalizeTime 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * PR_GMTParameters 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * PR_ImplodeTime 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * This was modified to use the Win32 SYSTEMTIME/FILETIME structures 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * and the timezone offsets are applied to the FILETIME structure. 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * All types and macros are defined in the base/third_party/prtime.h file. 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * These have been copied from the following nspr files. We have only copied 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * over the types we need. 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 1. prtime.h 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 2. prtypes.h 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 3. prlong.h 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/logging.h" 6733e712930d7cc5e45e5d8db87bfb3508cf773a6bKristian Monsen#include "base/third_party/nspr/prtime.h" 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "build/build_config.h" 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <windows.h> 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_MACOSX) 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <CoreFoundation/CoreFoundation.h> 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h> /* for EINVAL */ 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <time.h> 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* Implements the Unix localtime_r() function for windows */ 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void localtime_r(const time_t* secs, struct tm* time) { 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (void) localtime_s(time, secs); 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *------------------------------------------------------------------------ 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * PR_ImplodeTime -- 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Cf. time_t mktime(struct tm *tp) 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Note that 1 year has < 2^25 seconds. So an PRInt32 is large enough. 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *------------------------------------------------------------------------ 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPRTime 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPR_ImplodeTime(const PRExplodedTime *exploded) 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This is important, we want to make sure multiplications are 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // done with the correct precision. 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static const PRTime kSecondsToMicroseconds = static_cast<PRTime>(1000000); 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Create the system struct representing our exploded time. 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SYSTEMTIME st = {0}; 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FILETIME ft = {0}; 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ULARGE_INTEGER uli = {0}; 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott st.wYear = exploded->tm_year; 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott st.wMonth = exploded->tm_month + 1; 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott st.wDayOfWeek = exploded->tm_wday; 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott st.wDay = exploded->tm_mday; 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott st.wHour = exploded->tm_hour; 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott st.wMinute = exploded->tm_min; 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott st.wSecond = exploded->tm_sec; 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott st.wMilliseconds = exploded->tm_usec/1000; 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Convert to FILETIME. 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!SystemTimeToFileTime(&st, &ft)) { 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED() << "Unable to convert time"; 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Apply offsets. 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uli.LowPart = ft.dwLowDateTime; 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uli.HighPart = ft.dwHighDateTime; 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Convert from Windows epoch to NSPR epoch, and 100-nanoseconds units 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to microsecond units. 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRTime result = 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static_cast<PRTime>((uli.QuadPart / 10) - 11644473600000000i64); 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Adjust for time zone and dst. Convert from seconds to microseconds. 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result -= (exploded->tm_params.tp_gmt_offset + 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->tm_params.tp_dst_offset) * kSecondsToMicroseconds; 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_MACOSX) 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Create the system struct representing our exploded time. 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFGregorianDate gregorian_date; 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott gregorian_date.year = exploded->tm_year; 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott gregorian_date.month = exploded->tm_month + 1; 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott gregorian_date.day = exploded->tm_mday; 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott gregorian_date.hour = exploded->tm_hour; 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott gregorian_date.minute = exploded->tm_min; 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott gregorian_date.second = exploded->tm_sec; 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Compute |absolute_time| in seconds, correct for gmt and dst 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // (note the combined offset will be negative when we need to add it), then 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // convert to microseconds which is what PRTime expects. 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFAbsoluteTime absolute_time = 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFGregorianDateGetAbsoluteTime(gregorian_date, NULL); 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRTime result = static_cast<PRTime>(absolute_time); 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result -= exploded->tm_params.tp_gmt_offset + 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->tm_params.tp_dst_offset; 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result += kCFAbsoluteTimeIntervalSince1970; // PRTime epoch is 1970 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result *= kSecondsToMicroseconds; 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result += exploded->tm_usec; 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX) 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct tm exp_tm = {0}; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exp_tm.tm_sec = exploded->tm_sec; 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exp_tm.tm_min = exploded->tm_min; 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exp_tm.tm_hour = exploded->tm_hour; 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exp_tm.tm_mday = exploded->tm_mday; 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exp_tm.tm_mon = exploded->tm_month; 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exp_tm.tm_year = exploded->tm_year - 1900; 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time_t absolute_time = timegm(&exp_tm); 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If timegm returned -1. Since we don't pass it a time zone, the only 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // valid case of returning -1 is 1 second before Epoch (Dec 31, 1969). 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (absolute_time == -1 && 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott !(exploded->tm_year == 1969 && exploded->tm_month == 11 && 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->tm_mday == 31 && exploded->tm_hour == 23 && 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->tm_min == 59 && exploded->tm_sec == 59)) { 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If we get here, time_t must be 32 bits. 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Date was possibly too far in the future and would overflow. Return 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the most future date possible (year 2038). 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (exploded->tm_year >= 1970) 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return INT_MAX * kSecondsToMicroseconds; 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Date was possibly too far in the past and would underflow. Return 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the most past date possible (year 1901). 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return INT_MIN * kSecondsToMicroseconds; 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRTime result = static_cast<PRTime>(absolute_time); 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result -= exploded->tm_params.tp_gmt_offset + 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->tm_params.tp_dst_offset; 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result *= kSecondsToMicroseconds; 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result += exploded->tm_usec; 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#error No PR_ImplodeTime implemented on your platform. 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The COUNT_LEAPS macro counts the number of leap years passed by 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * till the start of the given year Y. At the start of the year 4 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * A.D. the number of leap years passed by is 0, while at the start of 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the year 5 A.D. this count is 1. The number of years divisible by 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 100 but not divisible by 400 (the non-leap years) is deducted from 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the count to get the correct number of leap years. 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The COUNT_DAYS macro counts the number of days since 01/01/01 till the 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * start of the given year Y. The number of days at the start of the year 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 1 is 0 while the number of days at the start of the year 2 is 365 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * (which is ((2)-1) * 365) and so on. The reference point is 01/01/01 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * midnight 00:00:00. 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define COUNT_LEAPS(Y) ( ((Y)-1)/4 - ((Y)-1)/100 + ((Y)-1)/400 ) 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define COUNT_DAYS(Y) ( ((Y)-1)*365 + COUNT_LEAPS(Y) ) 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DAYS_BETWEEN_YEARS(A, B) (COUNT_DAYS(B) - COUNT_DAYS(A)) 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Static variables used by functions in this file 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The following array contains the day of year for the last day of 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * each month, where index 1 is January, and day 0 is January 1. 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int lastDayOfMonth[2][13] = { 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364}, 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365} 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The number of days in a month 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const PRInt8 nDays[2][12] = { 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *------------------------------------------------------------------------- 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * IsLeapYear -- 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Returns 1 if the year is a leap year, 0 otherwise. 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *------------------------------------------------------------------------- 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int IsLeapYear(PRInt16 year) 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 1; 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 'secOffset' should be less than 86400 (i.e., a day). 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 'time' should point to a normalized PRExplodedTime. 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottApplySecOffset(PRExplodedTime *time, PRInt32 secOffset) 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_sec += secOffset; 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Note that in this implementation we do not count leap seconds */ 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_sec < 0 || time->tm_sec >= 60) { 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_min += time->tm_sec / 60; 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_sec %= 60; 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_sec < 0) { 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_sec += 60; 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_min--; 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_min < 0 || time->tm_min >= 60) { 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_hour += time->tm_min / 60; 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_min %= 60; 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_min < 0) { 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_min += 60; 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_hour--; 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_hour < 0) { 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Decrement mday, yday, and wday */ 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_hour += 24; 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_mday--; 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_yday--; 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_mday < 1) { 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_month--; 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_month < 0) { 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_month = 11; 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_year--; 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (IsLeapYear(time->tm_year)) 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_yday = 365; 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_yday = 364; 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_mday = nDays[IsLeapYear(time->tm_year)][time->tm_month]; 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_wday--; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_wday < 0) 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_wday = 6; 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (time->tm_hour > 23) { 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Increment mday, yday, and wday */ 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_hour -= 24; 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_mday++; 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_yday++; 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_mday > 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott nDays[IsLeapYear(time->tm_year)][time->tm_month]) { 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_mday = 1; 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_month++; 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_month > 11) { 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_month = 0; 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_year++; 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_yday = 0; 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_wday++; 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_wday > 6) 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_wday = 0; 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params) 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int daysInMonth; 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRInt32 numDays; 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Get back to GMT */ 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_sec -= time->tm_params.tp_gmt_offset 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott + time->tm_params.tp_dst_offset; 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_params.tp_gmt_offset = 0; 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_params.tp_dst_offset = 0; 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Now normalize GMT */ 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_usec < 0 || time->tm_usec >= 1000000) { 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_sec += time->tm_usec / 1000000; 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_usec %= 1000000; 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_usec < 0) { 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_usec += 1000000; 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_sec--; 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Note that we do not count leap seconds in this implementation */ 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_sec < 0 || time->tm_sec >= 60) { 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_min += time->tm_sec / 60; 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_sec %= 60; 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_sec < 0) { 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_sec += 60; 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_min--; 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_min < 0 || time->tm_min >= 60) { 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_hour += time->tm_min / 60; 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_min %= 60; 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_min < 0) { 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_min += 60; 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_hour--; 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_hour < 0 || time->tm_hour >= 24) { 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_mday += time->tm_hour / 24; 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_hour %= 24; 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_hour < 0) { 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_hour += 24; 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_mday--; 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Normalize month and year before mday */ 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_month < 0 || time->tm_month >= 12) { 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_year += time->tm_month / 12; 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_month %= 12; 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_month < 0) { 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_month += 12; 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_year--; 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Now that month and year are in proper range, normalize mday */ 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_mday < 1) { 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* mday too small */ 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* the previous month */ 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_month--; 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_month < 0) { 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_month = 11; 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_year--; 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_mday += nDays[IsLeapYear(time->tm_year)][time->tm_month]; 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (time->tm_mday < 1); 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott daysInMonth = nDays[IsLeapYear(time->tm_year)][time->tm_month]; 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (time->tm_mday > daysInMonth) { 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* mday too large */ 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_mday -= daysInMonth; 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_month++; 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_month > 11) { 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_month = 0; 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_year++; 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott daysInMonth = nDays[IsLeapYear(time->tm_year)][time->tm_month]; 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Recompute yday and wday */ 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_yday = time->tm_mday + 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott lastDayOfMonth[IsLeapYear(time->tm_year)][time->tm_month]; 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott numDays = DAYS_BETWEEN_YEARS(1970, time->tm_year) + time->tm_yday; 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_wday = (numDays + 4) % 7; 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (time->tm_wday < 0) { 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_wday += 7; 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Recompute time parameters */ 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time->tm_params = params(time); 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ApplySecOffset(time, time->tm_params.tp_gmt_offset 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott + time->tm_params.tp_dst_offset); 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *------------------------------------------------------------------------ 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * PR_GMTParameters -- 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Returns the PRTimeParameters for Greenwich Mean Time. 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Trivially, both the tp_gmt_offset and tp_dst_offset fields are 0. 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *------------------------------------------------------------------------ 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPRTimeParameters 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPR_GMTParameters(const PRExplodedTime *gmt) 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(XP_MAC) 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma unused (gmt) 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRTimeParameters retVal = { 0, 0 }; 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return retVal; 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The following code implements PR_ParseTimeString(). It is based on 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * ns/lib/xp/xp_time.c, revision 1.25, by Jamie Zawinski <jwz@netscape.com>. 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * We only recognize the abbreviations of a small subset of time zones 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * in North America, Europe, and Japan. 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * PST/PDT: Pacific Standard/Daylight Time 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * MST/MDT: Mountain Standard/Daylight Time 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * CST/CDT: Central Standard/Daylight Time 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * EST/EDT: Eastern Standard/Daylight Time 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * AST: Atlantic Standard Time 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * NST: Newfoundland Standard Time 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * GMT: Greenwich Mean Time 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * BST: British Summer Time 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * MET: Middle Europe Time 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * EET: Eastern Europe Time 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * JST: Japan Standard Time 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef enum 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TT_UNKNOWN, 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TT_SUN, TT_MON, TT_TUE, TT_WED, TT_THU, TT_FRI, TT_SAT, 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TT_JAN, TT_FEB, TT_MAR, TT_APR, TT_MAY, TT_JUN, 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TT_JUL, TT_AUG, TT_SEP, TT_OCT, TT_NOV, TT_DEC, 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TT_PST, TT_PDT, TT_MST, TT_MDT, TT_CST, TT_CDT, TT_EST, TT_EDT, 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TT_AST, TT_NST, TT_GMT, TT_BST, TT_MET, TT_EET, TT_JST 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} TIME_TOKEN; 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * This parses a time/date string into a PRTime 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * (microseconds after "1-Jan-1970 00:00:00 GMT"). 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * It returns PR_SUCCESS on success, and PR_FAILURE 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * if the time/date string can't be parsed. 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Many formats are handled, including: 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 14 Apr 89 03:20:12 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 14 Apr 89 03:20 GMT 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Fri, 17 Mar 89 4:01:33 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Fri, 17 Mar 89 4:01 GMT 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Mon Jan 16 16:12 PDT 1989 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Mon Jan 16 16:12 +0130 1989 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 6 May 1992 16:41-JST (Wednesday) 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 22-AUG-1993 10:59:12.82 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 22-AUG-1993 10:59pm 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 22-AUG-1993 12:59am 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 22-AUG-1993 12:59 PM 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Friday, August 04, 1995 3:54 PM 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 06/21/95 04:24:34 PM 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 20/06/95 21:07 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 95-06-08 19:32:48 EDT 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * If the input string doesn't contain a description of the timezone, 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * we consult the `default_to_gmt' to decide whether the string should 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * be interpreted relative to the local time zone (PR_FALSE) or GMT (PR_TRUE). 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The correct value for this argument depends on what standard specified 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the time string which you are parsing. 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPRStatus 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPR_ParseTimeString( 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *string, 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRBool default_to_gmt, 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRTime *result_imploded) 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRExplodedTime tm; 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRExplodedTime *result = &tm; 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TIME_TOKEN dotw = TT_UNKNOWN; 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TIME_TOKEN month = TT_UNKNOWN; 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TIME_TOKEN zone = TT_UNKNOWN; 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int zone_offset = -1; 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int dst_offset = 0; 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int date = -1; 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRInt32 year = -1; 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int hour = -1; 531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int min = -1; 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int sec = -1; 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *rest = string; 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int iterations = 0; 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_ASSERT(string && result); 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!string || !result) return PR_FAILURE; 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*rest) 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (iterations++ > 1000) 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return PR_FAILURE; 547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (*rest) 550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'a': case 'A': 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (month == TT_UNKNOWN && 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'p' || rest[1] == 'P') && 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'r' || rest[2] == 'R')) 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_APR; 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (zone == TT_UNKNOWN && 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 's' || rest[1] == 'S') && 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_AST; 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (month == TT_UNKNOWN && 561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'u' || rest[1] == 'U') && 562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'g' || rest[2] == 'G')) 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_AUG; 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'b': case 'B': 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (zone == TT_UNKNOWN && 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 's' || rest[1] == 'S') && 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_BST; 570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'c': case 'C': 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (zone == TT_UNKNOWN && 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'd' || rest[1] == 'D') && 574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_CDT; 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (zone == TT_UNKNOWN && 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 's' || rest[1] == 'S') && 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_CST; 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'd': case 'D': 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (month == TT_UNKNOWN && 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'e' || rest[1] == 'E') && 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'c' || rest[2] == 'C')) 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_DEC; 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'e': case 'E': 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (zone == TT_UNKNOWN && 589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'd' || rest[1] == 'D') && 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_EDT; 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (zone == TT_UNKNOWN && 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'e' || rest[1] == 'E') && 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_EET; 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (zone == TT_UNKNOWN && 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 's' || rest[1] == 'S') && 598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_EST; 600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'f': case 'F': 602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (month == TT_UNKNOWN && 603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'e' || rest[1] == 'E') && 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'b' || rest[2] == 'B')) 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_FEB; 606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (dotw == TT_UNKNOWN && 607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'r' || rest[1] == 'R') && 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'i' || rest[2] == 'I')) 609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dotw = TT_FRI; 610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'g': case 'G': 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (zone == TT_UNKNOWN && 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'm' || rest[1] == 'M') && 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_GMT; 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'j': case 'J': 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (month == TT_UNKNOWN && 619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'a' || rest[1] == 'A') && 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'n' || rest[2] == 'N')) 621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_JAN; 622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (zone == TT_UNKNOWN && 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 's' || rest[1] == 'S') && 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_JST; 626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (month == TT_UNKNOWN && 627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'u' || rest[1] == 'U') && 628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'l' || rest[2] == 'L')) 629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_JUL; 630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (month == TT_UNKNOWN && 631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'u' || rest[1] == 'U') && 632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'n' || rest[2] == 'N')) 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_JUN; 634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'm': case 'M': 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (month == TT_UNKNOWN && 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'a' || rest[1] == 'A') && 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'r' || rest[2] == 'R')) 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_MAR; 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (month == TT_UNKNOWN && 641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'a' || rest[1] == 'A') && 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'y' || rest[2] == 'Y')) 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_MAY; 644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (zone == TT_UNKNOWN && 645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'd' || rest[1] == 'D') && 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_MDT; 648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (zone == TT_UNKNOWN && 649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'e' || rest[1] == 'E') && 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_MET; 652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (dotw == TT_UNKNOWN && 653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'o' || rest[1] == 'O') && 654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'n' || rest[2] == 'N')) 655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dotw = TT_MON; 656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (zone == TT_UNKNOWN && 657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 's' || rest[1] == 'S') && 658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_MST; 660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'n': case 'N': 662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (month == TT_UNKNOWN && 663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'o' || rest[1] == 'O') && 664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'v' || rest[2] == 'V')) 665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_NOV; 666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (zone == TT_UNKNOWN && 667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 's' || rest[1] == 'S') && 668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_NST; 670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'o': case 'O': 672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (month == TT_UNKNOWN && 673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'c' || rest[1] == 'C') && 674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_OCT; 676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'p': case 'P': 678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (zone == TT_UNKNOWN && 679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'd' || rest[1] == 'D') && 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_PDT; 682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (zone == TT_UNKNOWN && 683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 's' || rest[1] == 'S') && 684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_PST; 686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 's': case 'S': 688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (dotw == TT_UNKNOWN && 689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'a' || rest[1] == 'A') && 690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 't' || rest[2] == 'T')) 691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dotw = TT_SAT; 692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (month == TT_UNKNOWN && 693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'e' || rest[1] == 'E') && 694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'p' || rest[2] == 'P')) 695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = TT_SEP; 696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (dotw == TT_UNKNOWN && 697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'u' || rest[1] == 'U') && 698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'n' || rest[2] == 'N')) 699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dotw = TT_SUN; 700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 't': case 'T': 702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (dotw == TT_UNKNOWN && 703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'h' || rest[1] == 'H') && 704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'u' || rest[2] == 'U')) 705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dotw = TT_THU; 706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (dotw == TT_UNKNOWN && 707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'u' || rest[1] == 'U') && 708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'e' || rest[2] == 'E')) 709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dotw = TT_TUE; 710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'u': case 'U': 712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (zone == TT_UNKNOWN && 713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 't' || rest[1] == 'T') && 714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott !(rest[2] >= 'A' && rest[2] <= 'Z') && 715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott !(rest[2] >= 'a' && rest[2] <= 'z')) 716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* UT is the same as GMT but UTx is not. */ 717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_GMT; 718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 'w': case 'W': 720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (dotw == TT_UNKNOWN && 721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1] == 'e' || rest[1] == 'E') && 722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2] == 'd' || rest[2] == 'D')) 723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dotw = TT_WED; 724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case '+': case '-': 727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *end; 729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int sign; 730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (zone_offset != -1) 731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* already got one... */ 733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest++; 734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (zone != TT_UNKNOWN && zone != TT_GMT) 737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* GMT+0300 is legal, but PST+0300 is not. */ 739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest++; 740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sign = ((*rest == '+') ? 1 : -1); 744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest++; /* move over sign */ 745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end = rest; 746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*end >= '0' && *end <= '9') 747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end++; 748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rest == end) /* no digits here */ 749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((end - rest) == 4) 752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* offset in HHMM */ 753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone_offset = (((((rest[0]-'0')*10) + (rest[1]-'0')) * 60) + 754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (((rest[2]-'0')*10) + (rest[3]-'0'))); 755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((end - rest) == 2) 756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* offset in hours */ 757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone_offset = (((rest[0]-'0')*10) + (rest[1]-'0')) * 60; 758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((end - rest) == 1) 759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* offset in hours */ 760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone_offset = (rest[0]-'0') * 60; 761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 3 or >4 */ 763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone_offset *= sign; 766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_GMT; 767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case '0': case '1': case '2': case '3': case '4': 771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case '5': case '6': case '7': case '8': case '9': 772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int tmp_hour = -1; 774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int tmp_min = -1; 775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int tmp_sec = -1; 776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *end = rest + 1; 777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*end >= '0' && *end <= '9') 778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end++; 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* end is now the first character after a range of digits. */ 781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*end == ':') 783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (hour >= 0 && min >= 0) /* already got it */ 785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* We have seen "[0-9]+:", so this is probably HH:MM[:SS] */ 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((end - rest) > 2) 789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* it is [0-9][0-9][0-9]+: */ 790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((end - rest) == 2) 792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_hour = ((rest[0]-'0')*10 + 793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1]-'0')); 794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_hour = (rest[0]-'0'); 796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* move over the colon, and parse minutes */ 798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest = ++end; 800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*end >= '0' && *end <= '9') 801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end++; 802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (end == rest) 804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* no digits after first colon? */ 805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((end - rest) > 2) 807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* it is [0-9][0-9][0-9]+: */ 808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((end - rest) == 2) 810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_min = ((rest[0]-'0')*10 + 811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1]-'0')); 812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_min = (rest[0]-'0'); 814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* now go for seconds */ 816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest = end; 817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*rest == ':') 818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest++; 819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end = rest; 820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*end >= '0' && *end <= '9') 821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end++; 822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (end == rest) 824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* no digits after second colon - that's ok. */ 825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ; 826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((end - rest) > 2) 827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* it is [0-9][0-9][0-9]+: */ 828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((end - rest) == 2) 830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_sec = ((rest[0]-'0')*10 + 831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1]-'0')); 832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_sec = (rest[0]-'0'); 834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* If we made it here, we've parsed hour and min, 836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott and possibly sec, so it worked as a unit. */ 837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* skip over whitespace and see if there's an AM or PM 839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott directly following the time. 840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (tmp_hour <= 12) 842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *s = end; 844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*s && (*s == ' ' || *s == '\t')) 845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott s++; 846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((s[0] == 'p' || s[0] == 'P') && 847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (s[1] == 'm' || s[1] == 'M')) 848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 10:05pm == 22:05, and 12:05pm == 12:05 */ 849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_hour = (tmp_hour == 12 ? 12 : tmp_hour + 12); 850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (tmp_hour == 12 && 851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (s[0] == 'a' || s[0] == 'A') && 852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (s[1] == 'm' || s[1] == 'M')) 853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 12:05am == 00:05 */ 854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_hour = 0; 855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott hour = tmp_hour; 858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott min = tmp_min; 859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sec = tmp_sec; 860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest = end; 861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((*end == '/' || *end == '-') && 864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end[1] >= '0' && end[1] <= '9') 865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Perhaps this is 6/16/95, 16/6/95, 6-16-95, or 16-6-95 867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott or even 95-06-05... 868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott #### But it doesn't handle 1995-06-22. 869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int n1, n2, n3; 871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *s; 872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (month != TT_UNKNOWN) 874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* if we saw a month name, this can't be. */ 875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott s = rest; 878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n1 = (*s++ - '0'); /* first 1 or 2 digits */ 880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*s >= '0' && *s <= '9') 881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n1 = n1*10 + (*s++ - '0'); 882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*s != '/' && *s != '-') /* slash */ 884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott s++; 886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*s < '0' || *s > '9') /* second 1 or 2 digits */ 888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n2 = (*s++ - '0'); 890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*s >= '0' && *s <= '9') 891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n2 = n2*10 + (*s++ - '0'); 892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*s != '/' && *s != '-') /* slash */ 894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott s++; 896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*s < '0' || *s > '9') /* third 1, 2, 4, or 5 digits */ 898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n3 = (*s++ - '0'); 900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*s >= '0' && *s <= '9') 901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n3 = n3*10 + (*s++ - '0'); 902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*s >= '0' && *s <= '9') /* optional digits 3, 4, and 5 */ 904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n3 = n3*10 + (*s++ - '0'); 906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*s < '0' || *s > '9') 907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n3 = n3*10 + (*s++ - '0'); 909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*s >= '0' && *s <= '9') 910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n3 = n3*10 + (*s++ - '0'); 911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((*s >= '0' && *s <= '9') || /* followed by non-alphanum */ 914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (*s >= 'A' && *s <= 'Z') || 915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (*s >= 'a' && *s <= 'z')) 916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Ok, we parsed three 1-2 digit numbers, with / or - 919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott between them. Now decide what the hell they are 920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (DD/MM/YY or MM/DD/YY or YY/MM/DD.) 921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (n1 > 31 || n1 == 0) /* must be YY/MM/DD */ 924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (n2 > 12) break; 926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (n3 > 31) break; 927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott year = n1; 928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (year < 70) 929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott year += 2000; 930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (year < 100) 931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott year += 1900; 932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1); 933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date = n3; 934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest = s; 935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (n1 > 12 && n2 > 12) /* illegal */ 939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest = s; 941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (n3 < 70) 945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n3 += 2000; 946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (n3 < 100) 947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n3 += 1900; 948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (n1 > 12) /* must be DD/MM/YY */ 950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date = n1; 952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1); 953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott year = n3; 954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else /* assume MM/DD/YY */ 956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* #### In the ambiguous case, should we consult the 958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott locale to find out the local default? */ 959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott month = (TIME_TOKEN)(n1 + ((int)TT_JAN) - 1); 960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date = n2; 961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott year = n3; 962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest = s; 964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((*end >= 'A' && *end <= 'Z') || 966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (*end >= 'a' && *end <= 'z')) 967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Digits followed by non-punctuation - what's that? */ 968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ; 969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((end - rest) == 5) /* five digits is a year */ 970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott year = (year < 0 971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ? ((rest[0]-'0')*10000L + 972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1]-'0')*1000L + 973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2]-'0')*100L + 974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[3]-'0')*10L + 975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[4]-'0')) 976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : year); 977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((end - rest) == 4) /* four digits is a year */ 978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott year = (year < 0 979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ? ((rest[0]-'0')*1000L + 980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1]-'0')*100L + 981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[2]-'0')*10L + 982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[3]-'0')) 983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : year); 984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((end - rest) == 2) /* two digits - date or year */ 985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int n = ((rest[0]-'0')*10 + 987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (rest[1]-'0')); 988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* If we don't have a date (day of the month) and we see a number 989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott less than 32, then assume that is the date. 990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Otherwise, if we have a date and not a year, assume this is the 992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott year. If it is less than 70, then assume it refers to the 21st 993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott century. If it is two digits (>= 70), assume it refers to this 994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott century. Otherwise, assume it refers to an unambiguous year. 995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott The world will surely end soon. 997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (date < 0 && n < 32) 999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date = n; 1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (year < 0) 1001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 1002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (n < 70) 1003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott year = 2000 + n; 1004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (n < 100) 1005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott year = 1900 + n; 1006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 1007c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott year = n; 1008c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* else what the hell is this. */ 1010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if ((end - rest) == 1) /* one digit - date */ 1012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date = (date < 0 ? (rest[0]-'0') : date); 1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* else, three or more than five digits - what's that? */ 1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Skip to the end of this token, whether we parsed it or not. 1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Tokens are delimited by whitespace, or ,;-/ 1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott But explicitly not :+-. 1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 1023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*rest && 1024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *rest != ' ' && *rest != '\t' && 1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *rest != ',' && *rest != ';' && 1026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *rest != '-' && *rest != '+' && 1027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *rest != '/' && 1028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *rest != '(' && *rest != ')' && *rest != '[' && *rest != ']') 1029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest++; 1030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* skip over uninteresting chars. */ 1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SKIP_MORE: 1032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*rest && 1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (*rest == ' ' || *rest == '\t' || 1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *rest == ',' || *rest == ';' || *rest == '/' || 1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *rest == '(' || *rest == ')' || *rest == '[' || *rest == ']')) 1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest++; 1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* "-" is ignored at the beginning of a token if we have not yet 1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed a year (e.g., the second "-" in "30-AUG-1966"), or if 1040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott the character after the dash is not a digit. */ 1041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*rest == '-' && ((rest > string && isalpha(rest[-1]) && year < 0) 1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott || rest[1] < '0' || rest[1] > '9')) 1043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 1044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rest++; 1045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott goto SKIP_MORE; 1046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1049c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (zone != TT_UNKNOWN && zone_offset == -1) 1051c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 1052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (zone) 1053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 1054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_PST: zone_offset = -8 * 60; break; 1055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_PDT: zone_offset = -8 * 60; dst_offset = 1 * 60; break; 1056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_MST: zone_offset = -7 * 60; break; 1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_MDT: zone_offset = -7 * 60; dst_offset = 1 * 60; break; 1058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_CST: zone_offset = -6 * 60; break; 1059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_CDT: zone_offset = -6 * 60; dst_offset = 1 * 60; break; 1060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_EST: zone_offset = -5 * 60; break; 1061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_EDT: zone_offset = -5 * 60; dst_offset = 1 * 60; break; 1062c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_AST: zone_offset = -4 * 60; break; 1063c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_NST: zone_offset = -3 * 60 - 30; break; 1064c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_GMT: zone_offset = 0 * 60; break; 1065c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_BST: zone_offset = 0 * 60; dst_offset = 1 * 60; break; 1066c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_MET: zone_offset = 1 * 60; break; 1067c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_EET: zone_offset = 2 * 60; break; 1068c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TT_JST: zone_offset = 9 * 60; break; 1069c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 1070c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_ASSERT (0); 1071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1072c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1075c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* If we didn't find a year, month, or day-of-the-month, we can't 1076c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott possibly parse this, and in fact, mktime() will do something random 1077c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (I'm seeing it return "Tue Feb 5 06:28:16 2036", which is no doubt 1078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott a numerologically significant date... */ 1079c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (month == TT_UNKNOWN || date == -1 || year == -1 || year > PR_INT16_MAX) 1080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return PR_FAILURE; 1081c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(result, 0, sizeof(*result)); 1083c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (sec != -1) 1084c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_sec = sec; 1085c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (min != -1) 1086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_min = min; 1087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (hour != -1) 1088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_hour = hour; 1089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (date != -1) 1090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_mday = date; 1091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (month != TT_UNKNOWN) 1092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_month = (((int)month) - ((int)TT_JAN)); 1093c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (year != -1) 1094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_year = year; 1095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (dotw != TT_UNKNOWN) 1096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_wday = (((int)dotw) - ((int)TT_SUN)); 1097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 1098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Mainly to compute wday and yday, but normalized time is also required 1099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * by the check below that works around a Visual C++ 2005 mktime problem. 1100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 1101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_NormalizeTime(result, PR_GMTParameters); 1102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* The remaining work is to set the gmt and dst offsets in tm_params. */ 1103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (zone == TT_UNKNOWN && default_to_gmt) 1105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 1106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* No zone was specified, so pretend the zone was GMT. */ 1107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone = TT_GMT; 1108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone_offset = 0; 1109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (zone_offset == -1) 1112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 1113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* no zone was specified, and we're to assume that everything 1114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott is local. */ 1115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct tm localTime; 1116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time_t secs; 1117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_ASSERT(result->tm_month > -1 && 1119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_mday > 0 && 1120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_hour > -1 && 1121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_min > -1 && 1122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_sec > -1); 1123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 1125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * To obtain time_t from a tm structure representing the local 1126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * time, we call mktime(). However, we need to see if we are 1127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * on 1-Jan-1970 or before. If we are, we can't call mktime() 1128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * because mktime() will crash on win16. In that case, we 1129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * calculate zone_offset based on the zone offset at 1130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 00:00:00, 2 Jan 1970 GMT, and subtract zone_offset from the 1131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * date we are parsing to transform the date to GMT. We also 1132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * do so if mktime() returns (time_t) -1 (time out of range). 1133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 1134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* month, day, hours, mins and secs are always non-negative 1136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott so we dont need to worry about them. */ 1137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if(result->tm_year >= 1970) 1138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 1139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRInt64 usec_per_sec; 1140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott localTime.tm_sec = result->tm_sec; 1142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott localTime.tm_min = result->tm_min; 1143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott localTime.tm_hour = result->tm_hour; 1144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott localTime.tm_mday = result->tm_mday; 1145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott localTime.tm_mon = result->tm_month; 1146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott localTime.tm_year = result->tm_year - 1900; 1147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Set this to -1 to tell mktime "I don't care". If you set 1148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott it to 0 or 1, you are making assertions about whether the 1149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date you are handing it is in daylight savings mode or not; 1150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott and if you're wrong, it will "fix" it for you. */ 1151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott localTime.tm_isdst = -1; 1152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if _MSC_VER == 1400 /* 1400 = Visual C++ 2005 (8.0) */ 1154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 1155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * mktime will return (time_t) -1 if the input is a date 1156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * after 23:59:59, December 31, 3000, US Pacific Time (not 1157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * UTC as documented): 1158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * http://msdn.microsoft.com/en-us/library/d1y53h2a(VS.80).aspx 1159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * But if the year is 3001, mktime also invokes the invalid 1160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * parameter handler, causing the application to crash. This 1161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * problem has been reported in 1162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=266036. 1163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * We avoid this crash by not calling mktime if the date is 1164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * out of range. To use a simple test that works in any time 1165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * zone, we consider year 3000 out of range as well. (See 1166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * bug 480740.) 1167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 1168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result->tm_year >= 3000) { 1169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Emulate what mktime would have done. */ 1170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott errno = EINVAL; 1171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott secs = (time_t) -1; 1172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott secs = mktime(&localTime); 1174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 1176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott secs = mktime(&localTime); 1177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 1178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (secs != (time_t) -1) 1179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 1180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRTime usecs64; 1181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LL_I2L(usecs64, secs); 1182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LL_I2L(usec_per_sec, PR_USEC_PER_SEC); 1183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LL_MUL(usecs64, usecs64, usec_per_sec); 1184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *result_imploded = usecs64; 1185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return PR_SUCCESS; 1186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* So mktime() can't handle this case. We assume the 1190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone_offset for the date we are parsing is the same as 1191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott the zone offset on 00:00:00 2 Jan 1970 GMT. */ 1192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott secs = 86400; 1193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott localtime_r(&secs, &localTime); 1194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott zone_offset = localTime.tm_min 1195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott + 60 * localTime.tm_hour 1196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott + 1440 * (localTime.tm_mday - 2); 1197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_params.tp_gmt_offset = zone_offset * 60; 1200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->tm_params.tp_dst_offset = dst_offset * 60; 1201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *result_imploded = PR_ImplodeTime(result); 1203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return PR_SUCCESS; 1204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1205