1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
|
/* $Id: datetype.c 551 2003-01-18 14:13:18Z twogood $ */
#include "synce.h"
#include <math.h>
#include <string.h>
#include <synce_log.h>
#define VAR_TIMEVALUEONLY DATE_TIMEVALUEONLY
#define VAR_DATEVALUEONLY DATE_DATEVALUEONLY
static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut );
static BOOL DateToTm( DATE dateIn, DWORD dwFlags, struct tm* pTm );
bool date_from_tm(struct tm* pTm, DATE *pDateOut)
{
struct tm copy = *pTm;
copy.tm_year += 1900;
return TmToDATE(©, pDateOut);
}
bool date_to_tm(DATE dateIn, DWORD dwFlags, struct tm* pTm)
{
struct tm result;
bool success = DateToTm(dateIn, dwFlags, &result);
if (success)
{
synce_trace("result.tm_year=%i", result.tm_year);
result.tm_year += 1900;
*pTm = result;
}
return success;
}
/*
* Note a leap year is one that is a multiple of 4
* but not of a 100. Except if it is a multiple of
* 400 then it is a leap year.
*/
#define isleap(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
/*
* Copyright 1998 Jean-Claude Cote
*
* These functions come from wine/dlls/oleaut32/variant.c in release 20020228
* of the WINE project. See http://www.winehq.org/ for more information.
*
* Licensing information for the code below:
*
* http://source.winehq.org/source/LICENSE?v=wine20020228
*
*/
/*
* Note a leap year is one that is a multiple of 4
* but not of a 100. Except if it is a multiple of
* 400 then it is a leap year.
*/
/* According to postgreSQL date parsing functions there is
* a leap year when this expression is true.
* (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
* So according to this there is 365.2515 days in one year.
* One + every four years: 1/4 -> 365.25
* One - every 100 years: 1/100 -> 365.01
* One + every 400 years: 1/400 -> 365.0025
*/
/* static const double DAYS_IN_ONE_YEAR = 365.2515;
*
* ^^ Might this be the key to an easy way to factor large prime numbers?
* Let's try using arithmetic. <lawson_whitney@juno.com> 7 Mar 2000
*/
static const double DAYS_IN_ONE_YEAR = 365.0; /*365.2425;*/
/******************************************************************************
* TmToDATE [INTERNAL]
*
* The date is implemented using an 8 byte floating-point number.
* Days are represented by whole numbers increments starting with 0.00 has
* being December 30 1899, midnight.
* The hours are expressed as the fractional part of the number.
* December 30 1899 at midnight = 0.00
* January 1 1900 at midnight = 2.00
* January 4 1900 at 6 AM = 5.25
* January 4 1900 at noon = 5.50
* December 29 1899 at midnight = -1.00
* December 18 1899 at midnight = -12.00
* December 18 1899 at 6AM = -12.25
* December 18 1899 at 6PM = -12.75
* December 19 1899 at midnight = -11.00
* The tm structure is as follows:
* struct tm {
* int tm_sec; seconds after the minute - [0,59]
* int tm_min; minutes after the hour - [0,59]
* int tm_hour; hours since midnight - [0,23]
* int tm_mday; day of the month - [1,31]
* int tm_mon; months since January - [0,11]
* int tm_year; years
* int tm_wday; days since Sunday - [0,6]
* int tm_yday; days since January 1 - [0,365]
* int tm_isdst; daylight savings time flag
* };
*
* Note: This function does not use the tm_wday, tm_yday, tm_wday,
* and tm_isdst fields of the tm structure. And only converts years
* after 1900.
*
* Returns TRUE if successful.
*/
static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
{
int leapYear = 0;
if( (pTm->tm_year - 1900) < 0 ) return FALSE;
/* Start at 1. This is the way DATE is defined.
* January 1, 1900 at Midnight is 1.00.
* January 1, 1900 at 6AM is 1.25.
* and so on.
*/
*pDateOut = 1;
/* Add the number of days corresponding to
* tm_year.
*/
*pDateOut += (pTm->tm_year - 1900) * 365;
/* Add the leap days in the previous years between now and 1900.
* Note a leap year is one that is a multiple of 4
* but not of a 100. Except if it is a multiple of
* 400 then it is a leap year.
*/
*pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
*pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
*pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
/* Set the leap year flag if the
* current year specified by tm_year is a
* leap year. This will be used to add a day
* to the day count.
*/
if( isleap( pTm->tm_year ) )
leapYear = 1;
/* Add the number of days corresponding to
* the month.
*/
switch( pTm->tm_mon )
{
case 2:
*pDateOut += 31;
break;
case 3:
*pDateOut += ( 59 + leapYear );
break;
case 4:
*pDateOut += ( 90 + leapYear );
break;
case 5:
*pDateOut += ( 120 + leapYear );
break;
case 6:
*pDateOut += ( 151 + leapYear );
break;
case 7:
*pDateOut += ( 181 + leapYear );
break;
case 8:
*pDateOut += ( 212 + leapYear );
break;
case 9:
*pDateOut += ( 243 + leapYear );
break;
case 10:
*pDateOut += ( 273 + leapYear );
break;
case 11:
*pDateOut += ( 304 + leapYear );
break;
case 12:
*pDateOut += ( 334 + leapYear );
break;
}
/* Add the number of days in this month.
*/
*pDateOut += pTm->tm_mday;
/* Add the number of seconds, minutes, and hours
* to the DATE. Note these are the fracionnal part
* of the DATE so seconds / number of seconds in a day.
*/
*pDateOut += pTm->tm_hour / 24.0;
*pDateOut += pTm->tm_min / 1440.0;
*pDateOut += pTm->tm_sec / 86400.0;
return TRUE;
}
/******************************************************************************
* DateToTm [INTERNAL]
*
* This function converts a windows DATE to a tm structure.
*
* It does not fill all the fields of the tm structure.
* Here is a list of the fields that are filled:
* tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
*
* Note this function does not support dates before the January 1, 1900
* or ( dateIn < 2.0 ).
*
* Returns TRUE if successful.
*/
static BOOL DateToTm( DATE dateIn, DWORD dwFlags, struct tm* pTm )
{
double decimalPart = 0.0;
double wholePart = 0.0;
/* Do not process dates smaller than January 1, 1900.
* Which corresponds to 2.0 in the windows DATE format.
*/
if( dateIn < 2.0 ) return FALSE;
memset(pTm,0,sizeof(*pTm));
/* Because of the nature of DATE format which
* associates 2.0 to January 1, 1900. We will
* remove 1.0 from the whole part of the DATE
* so that in the following code 1.0
* will correspond to January 1, 1900.
* This simplifies the processing of the DATE value.
*/
dateIn -= 1.0;
wholePart = (double) floor( dateIn );
decimalPart = fmod( dateIn, wholePart );
if( !(dwFlags & VAR_TIMEVALUEONLY) )
{
int nDay = 0;
int leapYear = 0;
double yearsSince1900 = 0;
/* Start at 1900, this is where the DATE time 0.0 starts.
*/
pTm->tm_year = 1900;
/* find in what year the day in the "wholePart" falls into.
* add the value to the year field.
*/
yearsSince1900 = floor( (wholePart / DAYS_IN_ONE_YEAR) + 0.001 );
pTm->tm_year += yearsSince1900;
/* determine if this is a leap year.
*/
if( isleap( pTm->tm_year ) )
{
leapYear = 1;
wholePart++;
}
/* find what day of that year the "wholePart" corresponds to.
* Note: nDay is in [1-366] format
*/
nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
/* Set the tm_yday value.
* Note: The day must be converted from [1-366] to [0-365]
*/
/*pTm->tm_yday = nDay - 1;*/
/* find which month this day corresponds to.
*/
if( nDay <= 31 )
{
pTm->tm_mday = nDay;
pTm->tm_mon = 0;
}
else if( nDay <= ( 59 + leapYear ) )
{
pTm->tm_mday = nDay - 31;
pTm->tm_mon = 1;
}
else if( nDay <= ( 90 + leapYear ) )
{
pTm->tm_mday = nDay - ( 59 + leapYear );
pTm->tm_mon = 2;
}
else if( nDay <= ( 120 + leapYear ) )
{
pTm->tm_mday = nDay - ( 90 + leapYear );
pTm->tm_mon = 3;
}
else if( nDay <= ( 151 + leapYear ) )
{
pTm->tm_mday = nDay - ( 120 + leapYear );
pTm->tm_mon = 4;
}
else if( nDay <= ( 181 + leapYear ) )
{
pTm->tm_mday = nDay - ( 151 + leapYear );
pTm->tm_mon = 5;
}
else if( nDay <= ( 212 + leapYear ) )
{
pTm->tm_mday = nDay - ( 181 + leapYear );
pTm->tm_mon = 6;
}
else if( nDay <= ( 243 + leapYear ) )
{
pTm->tm_mday = nDay - ( 212 + leapYear );
pTm->tm_mon = 7;
}
else if( nDay <= ( 273 + leapYear ) )
{
pTm->tm_mday = nDay - ( 243 + leapYear );
pTm->tm_mon = 8;
}
else if( nDay <= ( 304 + leapYear ) )
{
pTm->tm_mday = nDay - ( 273 + leapYear );
pTm->tm_mon = 9;
}
else if( nDay <= ( 334 + leapYear ) )
{
pTm->tm_mday = nDay - ( 304 + leapYear );
pTm->tm_mon = 10;
}
else if( nDay <= ( 365 + leapYear ) )
{
pTm->tm_mday = nDay - ( 334 + leapYear );
pTm->tm_mon = 11;
}
}
if( !(dwFlags & VAR_DATEVALUEONLY) )
{
/* find the number of seconds in this day.
* fractional part times, hours, minutes, seconds.
*/
pTm->tm_hour = (int) ( decimalPart * 24 );
pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
}
return TRUE;
}
|