Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
136fa03f
Commit
136fa03f
authored
Nov 14, 2003
by
Jon Griffiths
Committed by
Alexandre Julliard
Nov 14, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement the non-variant date conversions correctly, without going
through 'struct tm' first. Handle negative & 'rolling' dates too.
parent
2f558b53
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
416 additions
and
294 deletions
+416
-294
variant.c
dlls/oleaut32/variant.c
+416
-294
No files found.
dlls/oleaut32/variant.c
View file @
136fa03f
...
...
@@ -2,6 +2,10 @@
* VARIANT
*
* Copyright 1998 Jean-Claude Cote
* Copyright 2003 Jon Griffiths
* The alorithm for conversion from Julian days to day/month/year is based on
* that devised by Henry Fliegel, as implemented in PostgreSQL, which is
* Copyright 1994-7 Regents of the University of California
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -4206,27 +4210,427 @@ error:
return
DISP_E_TYPEMISMATCH
;
}
/* Date Conversions */
#define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
/* Convert a VT_DATE value to a Julian Date */
static
inline
int
VARIANT_JulianFromDate
(
int
dateIn
)
{
int
julianDays
=
dateIn
;
julianDays
-=
DATE_MIN
;
/* Convert to + days from 1 Jan 100 AD */
julianDays
+=
1757585
;
/* Convert to + days from 23 Nov 4713 BC (Julian) */
return
julianDays
;
}
/* Convert a Julian Date to a VT_DATE value */
static
inline
int
VARIANT_DateFromJulian
(
int
dateIn
)
{
int
julianDays
=
dateIn
;
julianDays
-=
1757585
;
/* Convert to + days from 1 Jan 100 AD */
julianDays
+=
DATE_MIN
;
/* Convert to +/- days from 1 Jan 1899 AD */
return
julianDays
;
}
/* Convert a Julian date to Day/Month/Year - from PostgreSQL */
static
inline
void
VARIANT_DMYFromJulian
(
int
jd
,
USHORT
*
year
,
USHORT
*
month
,
USHORT
*
day
)
{
int
j
,
i
,
l
,
n
;
l
=
jd
+
68569
;
n
=
l
*
4
/
146097
;
l
-=
(
n
*
146097
+
3
)
/
4
;
i
=
(
4000
*
(
l
+
1
))
/
1461001
;
l
+=
31
-
(
i
*
1461
)
/
4
;
j
=
(
l
*
80
)
/
2447
;
*
day
=
l
-
(
j
*
2447
)
/
80
;
l
=
j
/
11
;
*
month
=
(
j
+
2
)
-
(
12
*
l
);
*
year
=
100
*
(
n
-
49
)
+
i
+
l
;
}
/* Convert Day/Month/Year to a Julian date - from PostgreSQL */
static
inline
double
VARIANT_JulianFromDMY
(
USHORT
year
,
USHORT
month
,
USHORT
day
)
{
int
m12
=
(
month
-
14
)
/
12
;
return
((
1461
*
(
year
+
4800
+
m12
))
/
4
+
(
367
*
(
month
-
2
-
12
*
m12
))
/
12
-
(
3
*
((
year
+
4900
+
m12
)
/
100
))
/
4
+
day
-
32075
);
}
/* Macros for accessing DOS format date/time fields */
#define DOS_YEAR(x) (1980 + (x >> 9))
#define DOS_MONTH(x) ((x >> 5) & 0xf)
#define DOS_DAY(x) (x & 0x1f)
#define DOS_HOUR(x) (x >> 11)
#define DOS_MINUTE(x) ((x >> 5) & 0x3f)
#define DOS_SECOND(x) ((x & 0x1f) << 1)
/* Create a DOS format date/time */
#define DOS_DATE(d,m,y) (d | (m << 5) | ((y-1980) << 9))
#define DOS_TIME(h,m,s) ((s >> 1) | (m << 5) | (h << 11))
/* Roll a date forwards or backwards to correct it */
static
HRESULT
VARIANT_RollUdate
(
UDATE
*
lpUd
)
{
static
const
BYTE
days
[]
=
{
0
,
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
};
TRACE
(
"Raw date: %d/%d/%d %d:%d:%d
\n
"
,
lpUd
->
st
.
wDay
,
lpUd
->
st
.
wMonth
,
lpUd
->
st
.
wYear
,
lpUd
->
st
.
wHour
,
lpUd
->
st
.
wMinute
,
lpUd
->
st
.
wSecond
);
/* Years < 100 are treated as 1900 + year */
if
(
lpUd
->
st
.
wYear
<
100
)
lpUd
->
st
.
wYear
+=
1900
;
if
(
!
lpUd
->
st
.
wMonth
)
{
/* Roll back to December of the previous year */
lpUd
->
st
.
wMonth
=
12
;
lpUd
->
st
.
wYear
--
;
}
else
while
(
lpUd
->
st
.
wMonth
>
12
)
{
/* Roll forward the correct number of months */
lpUd
->
st
.
wYear
++
;
lpUd
->
st
.
wMonth
-=
12
;
}
if
(
lpUd
->
st
.
wYear
>
9999
||
lpUd
->
st
.
wHour
>
23
||
lpUd
->
st
.
wMinute
>
59
||
lpUd
->
st
.
wSecond
>
59
)
return
E_INVALIDARG
;
/* Invalid values */
if
(
!
lpUd
->
st
.
wDay
)
{
/* Roll back the date one day */
if
(
lpUd
->
st
.
wMonth
==
1
)
{
/* Roll back to December 31 of the previous year */
lpUd
->
st
.
wDay
=
31
;
lpUd
->
st
.
wMonth
=
12
;
lpUd
->
st
.
wYear
--
;
}
else
{
lpUd
->
st
.
wMonth
--
;
/* Previous month */
if
(
lpUd
->
st
.
wMonth
==
2
&&
IsLeapYear
(
lpUd
->
st
.
wYear
))
lpUd
->
st
.
wDay
=
29
;
/* Februaury has 29 days on leap years */
else
lpUd
->
st
.
wDay
=
days
[
lpUd
->
st
.
wMonth
];
/* Last day of the month */
}
}
else
if
(
lpUd
->
st
.
wDay
>
28
)
{
int
rollForward
=
0
;
/* Possibly need to roll the date forward */
if
(
lpUd
->
st
.
wMonth
==
2
&&
IsLeapYear
(
lpUd
->
st
.
wYear
))
rollForward
=
lpUd
->
st
.
wDay
-
29
;
/* Februaury has 29 days on leap years */
else
rollForward
=
lpUd
->
st
.
wDay
-
days
[
lpUd
->
st
.
wMonth
];
if
(
rollForward
>
0
)
{
lpUd
->
st
.
wDay
=
rollForward
;
lpUd
->
st
.
wMonth
++
;
if
(
lpUd
->
st
.
wMonth
>
12
)
{
lpUd
->
st
.
wMonth
=
1
;
/* Roll forward into January of the next year */
lpUd
->
st
.
wYear
++
;
}
}
}
TRACE
(
"Rolled date: %d/%d/%d %d:%d:%d
\n
"
,
lpUd
->
st
.
wDay
,
lpUd
->
st
.
wMonth
,
lpUd
->
st
.
wYear
,
lpUd
->
st
.
wHour
,
lpUd
->
st
.
wMinute
,
lpUd
->
st
.
wSecond
);
return
S_OK
;
}
/**********************************************************************
* DosDateTimeToVariantTime [OLEAUT32.14]
* Convert dos representation of time to the date and time representation
* stored in a variant.
*
* Convert a Dos format date and time into variant VT_DATE format.
*
* PARAMS
* wDosDate [I] Dos format date
* wDosTime [I] Dos format time
* pDateOut [O] Destination for VT_DATE format
*
* RETURNS
* Success: TRUE. pDateOut contains the converted time.
* Failure: FALSE, if wDosDate or wDosTime are invalid (see notes).
*
* NOTES
* - Dos format dates can only hold dates from 1-Jan-1980 to 31-Dec-2099.
* - Dos format times are accurate to only 2 second precision.
* - The format of a Dos Date is:
*| Bits Values Meaning
*| ---- ------ -------
*| 0-4 1-31 Day of the week. 0 rolls back one day. A value greater than
*| the days in the month rolls forward the extra days.
*| 5-8 1-12 Month of the year. 0 rolls back to December of the previous
*| year. 13-15 are invalid.
*| 9-15 0-119 Year based from 1980 (Max 2099). 120-127 are invalid.
* - The format of a Dos Time is:
*| Bits Values Meaning
*| ---- ------ -------
*| 0-4 0-29 Seconds/2. 30 and 31 are invalid.
*| 5-10 0-59 Minutes. 60-63 are invalid.
*| 11-15 0-23 Hours (24 hour clock). 24-32 are invalid.
*/
INT
WINAPI
DosDateTimeToVariantTime
(
USHORT
wDosDate
,
USHORT
wDosTime
,
DATE
*
pvtime
)
double
*
pDateOut
)
{
UDATE
ud
;
TRACE
(
"(0x%x(%d/%d/%d),0x%x(%d:%d:%d),%p)
\n
"
,
wDosDate
,
DOS_YEAR
(
wDosDate
),
DOS_MONTH
(
wDosDate
),
DOS_DAY
(
wDosDate
),
wDosTime
,
DOS_HOUR
(
wDosTime
),
DOS_MINUTE
(
wDosTime
),
DOS_SECOND
(
wDosTime
),
pDateOut
);
ud
.
st
.
wYear
=
DOS_YEAR
(
wDosDate
);
ud
.
st
.
wMonth
=
DOS_MONTH
(
wDosDate
);
if
(
ud
.
st
.
wYear
>
2099
||
ud
.
st
.
wMonth
>
12
)
return
FALSE
;
ud
.
st
.
wDay
=
DOS_DAY
(
wDosDate
);
ud
.
st
.
wHour
=
DOS_HOUR
(
wDosTime
);
ud
.
st
.
wMinute
=
DOS_MINUTE
(
wDosTime
);
ud
.
st
.
wSecond
=
DOS_SECOND
(
wDosTime
);
ud
.
st
.
wDayOfWeek
=
ud
.
st
.
wMilliseconds
=
0
;
return
!
VarDateFromUdate
(
&
ud
,
0
,
pDateOut
);
}
/**********************************************************************
* VariantTimeToDosDateTime [OLEAUT32.13]
*
* Convert a variant format date into a Dos format date and time.
*
* dateIn [I] VT_DATE time format
* pwDosDate [O] Destination for Dos format date
* pwDosTime [O] Destination for Dos format time
*
* RETURNS
* Success: TRUE. pwDosDate and pwDosTime contains the converted values.
* Failure: FALSE, if dateIn cannot be represented in Dos format.
*
* NOTES
* See DosDateTimeToVariantTime() for Dos format details and bugs.
*/
INT
WINAPI
VariantTimeToDosDateTime
(
double
dateIn
,
USHORT
*
pwDosDate
,
USHORT
*
pwDosTime
)
{
UDATE
ud
;
TRACE
(
"(%g,%p,%p)
\n
"
,
dateIn
,
pwDosDate
,
pwDosTime
);
if
(
FAILED
(
VarUdateFromDate
(
dateIn
,
0
,
&
ud
)))
return
FALSE
;
if
(
ud
.
st
.
wYear
<
1980
||
ud
.
st
.
wYear
>
2099
)
return
FALSE
;
*
pwDosDate
=
DOS_DATE
(
ud
.
st
.
wDay
,
ud
.
st
.
wMonth
,
ud
.
st
.
wYear
);
*
pwDosTime
=
DOS_TIME
(
ud
.
st
.
wHour
,
ud
.
st
.
wMinute
,
ud
.
st
.
wSecond
);
TRACE
(
"Returning 0x%x(%d/%d/%d), 0x%x(%d:%d:%d)
\n
"
,
*
pwDosDate
,
DOS_YEAR
(
*
pwDosDate
),
DOS_MONTH
(
*
pwDosDate
),
DOS_DAY
(
*
pwDosDate
),
*
pwDosTime
,
DOS_HOUR
(
*
pwDosTime
),
DOS_MINUTE
(
*
pwDosTime
),
DOS_SECOND
(
*
pwDosTime
));
return
TRUE
;
}
/***********************************************************************
* SystemTimeToVariantTime [OLEAUT32.184]
*
* Convert a System format date and time into variant VT_DATE format.
*
* PARAMS
* lpSt [I] System format date and time
* pDateOut [O] Destination for VT_DATE format date
*
* RETURNS
* Success: TRUE. *pDateOut contains the converted value.
* Failure: FALSE, if lpSt cannot be represented in VT_DATE format.
*/
INT
WINAPI
SystemTimeToVariantTime
(
LPSYSTEMTIME
lpSt
,
double
*
pDateOut
)
{
UDATE
ud
;
TRACE
(
"(%p->%d/%d/%d %d:%d:%d,%p)
\n
"
,
lpSt
,
lpSt
->
wDay
,
lpSt
->
wMonth
,
lpSt
->
wYear
,
lpSt
->
wHour
,
lpSt
->
wMinute
,
lpSt
->
wSecond
,
pDateOut
);
if
(
lpSt
->
wMonth
>
12
)
return
FALSE
;
memcpy
(
&
ud
.
st
,
lpSt
,
sizeof
(
ud
.
st
));
return
!
VarDateFromUdate
(
&
ud
,
0
,
pDateOut
);
}
/***********************************************************************
* VariantTimeToSystemTime [OLEAUT32.185]
*
* Convert a variant VT_DATE into a System format date and time.
*
* PARAMS
* datein [I] Variant VT_DATE format date
* lpSt [O] Destination for System format date and time
*
* RETURNS
* Success: TRUE. *lpSt contains the converted value.
* Failure: FALSE, if dateIn is too large or small.
*/
INT
WINAPI
VariantTimeToSystemTime
(
double
dateIn
,
LPSYSTEMTIME
lpSt
)
{
UDATE
ud
;
TRACE
(
"(%g,%p)
\n
"
,
dateIn
,
lpSt
);
if
(
FAILED
(
VarUdateFromDate
(
dateIn
,
0
,
&
ud
)))
return
FALSE
;
memcpy
(
lpSt
,
&
ud
.
st
,
sizeof
(
ud
.
st
));
return
TRUE
;
}
/***********************************************************************
* VarDateFromUdate [OLEAUT32.330]
*
* Convert an unpacked format date and time to a variant VT_DATE.
*
* PARAMS
* pUdateIn [I] Unpacked format date and time to convert
* dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
* pDateOut [O] Destination for variant VT_DATE.
*
* RETURNS
* Success: S_OK. *pDateOut contains the converted value.
* Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format.
*/
HRESULT
WINAPI
VarDateFromUdate
(
UDATE
*
pUdateIn
,
ULONG
dwFlags
,
DATE
*
pDateOut
)
{
UDATE
ud
;
double
dateVal
;
TRACE
(
"(%p->%d/%d/%d %d:%d:%d:%d %d %d,0x%08lx,%p)
\n
"
,
pUdateIn
,
pUdateIn
->
st
.
wMonth
,
pUdateIn
->
st
.
wDay
,
pUdateIn
->
st
.
wYear
,
pUdateIn
->
st
.
wHour
,
pUdateIn
->
st
.
wMinute
,
pUdateIn
->
st
.
wSecond
,
pUdateIn
->
st
.
wMilliseconds
,
pUdateIn
->
st
.
wDayOfWeek
,
pUdateIn
->
wDayOfYear
,
dwFlags
,
pDateOut
);
memcpy
(
&
ud
,
pUdateIn
,
sizeof
(
ud
));
if
(
dwFlags
&
VAR_VALIDDATE
)
WARN
(
"Ignoring VAR_VALIDDATE
\n
"
);
if
(
FAILED
(
VARIANT_RollUdate
(
&
ud
)))
return
E_INVALIDARG
;
/* Date */
dateVal
=
VARIANT_DateFromJulian
(
VARIANT_JulianFromDMY
(
ud
.
st
.
wYear
,
ud
.
st
.
wMonth
,
ud
.
st
.
wDay
));
/* Time */
dateVal
+=
ud
.
st
.
wHour
/
24
.
0
;
dateVal
+=
ud
.
st
.
wMinute
/
1440
.
0
;
dateVal
+=
ud
.
st
.
wSecond
/
86400
.
0
;
dateVal
+=
ud
.
st
.
wMilliseconds
/
86400000
.
0
;
TRACE
(
"Returning %g
\n
"
,
dateVal
);
*
pDateOut
=
dateVal
;
return
S_OK
;
}
/***********************************************************************
* VarUdateFromDate [OLEAUT32.331]
*
* Convert a variant VT_DATE into an unpacked format date and time.
*
* PARAMS
* datein [I] Variant VT_DATE format date
* dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
* lpUdate [O] Destination for unpacked format date and time
*
* RETURNS
* Success: S_OK. *lpUdate contains the converted value.
* Failure: E_INVALIDARG, if dateIn is too large or small.
*/
HRESULT
WINAPI
VarUdateFromDate
(
DATE
dateIn
,
ULONG
dwFlags
,
UDATE
*
lpUdate
)
{
struct
tm
t
;
/* Cumulative totals of days per month */
static
const
USHORT
cumulativeDays
[]
=
{
0
,
0
,
31
,
59
,
90
,
120
,
151
,
181
,
212
,
243
,
273
,
304
,
334
};
double
datePart
,
timePart
;
int
julianDays
;
TRACE
(
"( 0x%x, 0x%x, %p ), stub
\n
"
,
wDosDate
,
wDosTime
,
pvtime
);
TRACE
(
"(%g,0x%08lx,%p)
\n
"
,
dateIn
,
dwFlags
,
lpUdate
);
t
.
tm_sec
=
(
wDosTime
&
0x001f
)
*
2
;
t
.
tm_min
=
(
wDosTime
&
0x07e0
)
>>
5
;
t
.
tm_hour
=
(
wDosTime
&
0xf800
)
>>
11
;
if
(
dateIn
<=
(
DATE_MIN
-
1
.
0
)
||
dateIn
>=
(
DATE_MAX
+
1
.
0
))
return
E_INVALIDARG
;
t
.
tm_mday
=
(
wDosDate
&
0x001f
);
t
.
tm_mon
=
(
wDosDate
&
0x01e0
)
>>
5
;
t
.
tm_year
=
((
wDosDate
&
0xfe00
)
>>
9
)
+
1980
;
datePart
=
dateIn
<
0
.
0
?
ceil
(
dateIn
)
:
floor
(
dateIn
);
/* Compensate for int truncation (always downwards) */
timePart
=
dateIn
-
datePart
+
0
.
00000000001
;
if
(
timePart
>=
1
.
0
)
timePart
-=
0
.
00000000001
;
/* Date */
julianDays
=
VARIANT_JulianFromDate
(
dateIn
);
VARIANT_DMYFromJulian
(
julianDays
,
&
lpUdate
->
st
.
wYear
,
&
lpUdate
->
st
.
wMonth
,
&
lpUdate
->
st
.
wDay
);
datePart
=
(
datePart
+
1
.
5
)
/
7
.
0
;
lpUdate
->
st
.
wDayOfWeek
=
(
datePart
-
floor
(
datePart
))
*
7
;
if
(
lpUdate
->
st
.
wDayOfWeek
==
0
)
lpUdate
->
st
.
wDayOfWeek
=
5
;
else
if
(
lpUdate
->
st
.
wDayOfWeek
==
1
)
lpUdate
->
st
.
wDayOfWeek
=
6
;
else
lpUdate
->
st
.
wDayOfWeek
-=
2
;
return
TmToDATE
(
&
t
,
pvtime
);
if
(
lpUdate
->
st
.
wMonth
>
2
&&
IsLeapYear
(
lpUdate
->
st
.
wYear
))
lpUdate
->
wDayOfYear
=
1
;
/* After February, in a leap year */
else
lpUdate
->
wDayOfYear
=
0
;
lpUdate
->
wDayOfYear
+=
cumulativeDays
[
lpUdate
->
st
.
wMonth
];
lpUdate
->
wDayOfYear
+=
lpUdate
->
st
.
wDay
;
/* Time */
timePart
*=
24
.
0
;
lpUdate
->
st
.
wHour
=
timePart
;
timePart
-=
lpUdate
->
st
.
wHour
;
timePart
*=
60
.
0
;
lpUdate
->
st
.
wMinute
=
timePart
;
timePart
-=
lpUdate
->
st
.
wMinute
;
timePart
*=
60
.
0
;
lpUdate
->
st
.
wSecond
=
timePart
;
timePart
-=
lpUdate
->
st
.
wSecond
;
lpUdate
->
st
.
wMilliseconds
=
0
;
if
(
timePart
>
0
.
0005
)
{
/* Round the milliseconds, adjusting the time/date forward if needed */
if
(
lpUdate
->
st
.
wSecond
<
59
)
lpUdate
->
st
.
wSecond
++
;
else
{
lpUdate
->
st
.
wSecond
=
0
;
if
(
lpUdate
->
st
.
wMinute
<
59
)
lpUdate
->
st
.
wMinute
++
;
else
{
lpUdate
->
st
.
wMinute
=
0
;
if
(
lpUdate
->
st
.
wHour
<
23
)
lpUdate
->
st
.
wHour
++
;
else
{
lpUdate
->
st
.
wHour
=
0
;
/* Roll over a whole day */
if
(
++
lpUdate
->
st
.
wDay
>
28
)
VARIANT_RollUdate
(
lpUdate
);
}
}
}
}
return
S_OK
;
}
#define GET_NUMBER_TEXT(fld,name) \
...
...
@@ -5004,288 +5408,6 @@ HRESULT WINAPI VarFormatCurrency(LPVARIANT var, INT digits, INT lead, INT paren,
}
/**********************************************************************
* VariantTimeToDosDateTime [OLEAUT32.13]
* Convert variant representation of time to the date and time representation
* stored in dos.
*/
INT
WINAPI
VariantTimeToDosDateTime
(
DATE
pvtime
,
USHORT
*
wDosDate
,
USHORT
*
wDosTime
)
{
struct
tm
t
;
*
wDosTime
=
0
;
*
wDosDate
=
0
;
TRACE
(
"( 0x%x, 0x%x, %p ), stub
\n
"
,
*
wDosDate
,
*
wDosTime
,
&
pvtime
);
if
(
DateToTm
(
pvtime
,
0
,
&
t
)
<
0
)
return
0
;
*
wDosTime
=
*
wDosTime
|
(
t
.
tm_sec
/
2
);
*
wDosTime
=
*
wDosTime
|
(
t
.
tm_min
<<
5
);
*
wDosTime
=
*
wDosTime
|
(
t
.
tm_hour
<<
11
);
*
wDosDate
=
*
wDosDate
|
t
.
tm_mday
;
*
wDosDate
=
*
wDosDate
|
t
.
tm_mon
<<
5
;
*
wDosDate
=
*
wDosDate
|
((
t
.
tm_year
-
1980
)
<<
9
)
;
return
1
;
}
/***********************************************************************
* SystemTimeToVariantTime [OLEAUT32.184]
*/
HRESULT
WINAPI
SystemTimeToVariantTime
(
LPSYSTEMTIME
lpSystemTime
,
double
*
pvtime
)
{
struct
tm
t
;
TRACE
(
" %d/%d/%d %d:%d:%d
\n
"
,
lpSystemTime
->
wMonth
,
lpSystemTime
->
wDay
,
lpSystemTime
->
wYear
,
lpSystemTime
->
wHour
,
lpSystemTime
->
wMinute
,
lpSystemTime
->
wSecond
);
if
(
lpSystemTime
->
wYear
>=
1900
)
{
t
.
tm_sec
=
lpSystemTime
->
wSecond
;
t
.
tm_min
=
lpSystemTime
->
wMinute
;
t
.
tm_hour
=
lpSystemTime
->
wHour
;
t
.
tm_mday
=
lpSystemTime
->
wDay
;
t
.
tm_mon
=
lpSystemTime
->
wMonth
-
1
;
/* tm_mon is 0..11, wMonth is 1..12 */
t
.
tm_year
=
lpSystemTime
->
wYear
;
return
TmToDATE
(
&
t
,
pvtime
);
}
else
{
double
tmpDate
;
long
firstDayOfNextYear
;
long
thisDay
;
long
leftInYear
;
long
result
;
double
decimalPart
=
0
.
0
;
t
.
tm_sec
=
lpSystemTime
->
wSecond
;
t
.
tm_min
=
lpSystemTime
->
wMinute
;
t
.
tm_hour
=
lpSystemTime
->
wHour
;
/* Step year forward the same number of years before 1900 */
t
.
tm_year
=
1900
+
1899
-
lpSystemTime
->
wYear
;
t
.
tm_mon
=
lpSystemTime
->
wMonth
-
1
;
t
.
tm_mday
=
lpSystemTime
->
wDay
;
/* Calculate date */
TmToDATE
(
&
t
,
pvtime
);
thisDay
=
(
double
)
floor
(
*
pvtime
);
decimalPart
=
fmod
(
*
pvtime
,
thisDay
);
/* Now, calculate the same time for the first of Jan that year */
t
.
tm_mon
=
0
;
t
.
tm_mday
=
1
;
t
.
tm_sec
=
0
;
t
.
tm_min
=
0
;
t
.
tm_hour
=
0
;
t
.
tm_year
=
t
.
tm_year
+
1
;
TmToDATE
(
&
t
,
&
tmpDate
);
firstDayOfNextYear
=
(
long
)
floor
(
tmpDate
);
/* Finally since we know the size of the year, subtract the two to get
remaining time in the year */
leftInYear
=
firstDayOfNextYear
-
thisDay
;
/* Now we want full years up to the year in question, and remainder of year
of the year in question */
if
(
isleap
(
lpSystemTime
->
wYear
)
)
{
TRACE
(
"Extra day due to leap year
\n
"
);
result
=
2
.
0
-
((
firstDayOfNextYear
-
366
)
+
leftInYear
-
2
.
0
);
}
else
{
result
=
2
.
0
-
((
firstDayOfNextYear
-
365
)
+
leftInYear
-
2
.
0
);
}
*
pvtime
=
(
double
)
result
+
decimalPart
;
TRACE
(
"<1899 support: returned %f, 1st day %ld, thisday %ld, left %ld
\n
"
,
*
pvtime
,
firstDayOfNextYear
,
thisDay
,
leftInYear
);
return
1
;
}
return
0
;
}
/***********************************************************************
* VariantTimeToSystemTime [OLEAUT32.185]
*/
HRESULT
WINAPI
VariantTimeToSystemTime
(
double
vtime
,
LPSYSTEMTIME
lpSystemTime
)
{
double
t
=
0
,
timeofday
=
0
;
static
const
BYTE
Days_Per_Month
[]
=
{
0
,
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
};
static
const
BYTE
Days_Per_Month_LY
[]
=
{
0
,
31
,
29
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
};
/* The Month_Code is used to find the Day of the Week (LY = LeapYear)*/
static
const
BYTE
Month_Code
[]
=
{
0
,
1
,
4
,
4
,
0
,
2
,
5
,
0
,
3
,
6
,
1
,
4
,
6
};
static
const
BYTE
Month_Code_LY
[]
=
{
0
,
0
,
3
,
4
,
0
,
2
,
5
,
0
,
3
,
6
,
1
,
4
,
6
};
/* The Century_Code is used to find the Day of the Week */
static
const
BYTE
Century_Code
[]
=
{
0
,
6
,
4
,
2
};
struct
tm
r
;
TRACE
(
" Variant = %f SYSTEMTIME ptr %p
\n
"
,
vtime
,
lpSystemTime
);
if
(
vtime
>=
0
)
{
if
(
DateToTm
(
vtime
,
0
,
&
r
)
<=
0
)
return
0
;
lpSystemTime
->
wSecond
=
r
.
tm_sec
;
lpSystemTime
->
wMinute
=
r
.
tm_min
;
lpSystemTime
->
wHour
=
r
.
tm_hour
;
lpSystemTime
->
wDay
=
r
.
tm_mday
;
lpSystemTime
->
wMonth
=
r
.
tm_mon
;
if
(
lpSystemTime
->
wMonth
==
12
)
lpSystemTime
->
wMonth
=
1
;
else
lpSystemTime
->
wMonth
++
;
lpSystemTime
->
wYear
=
r
.
tm_year
;
}
else
{
vtime
=
-
1
*
vtime
;
if
(
DateToTm
(
vtime
,
0
,
&
r
)
<=
0
)
return
0
;
lpSystemTime
->
wSecond
=
r
.
tm_sec
;
lpSystemTime
->
wMinute
=
r
.
tm_min
;
lpSystemTime
->
wHour
=
r
.
tm_hour
;
lpSystemTime
->
wMonth
=
13
-
r
.
tm_mon
;
if
(
lpSystemTime
->
wMonth
==
1
)
lpSystemTime
->
wMonth
=
12
;
else
lpSystemTime
->
wMonth
--
;
lpSystemTime
->
wYear
=
1899
-
(
r
.
tm_year
-
1900
);
if
(
!
isleap
(
lpSystemTime
->
wYear
)
)
lpSystemTime
->
wDay
=
Days_Per_Month
[
13
-
lpSystemTime
->
wMonth
]
-
r
.
tm_mday
;
else
lpSystemTime
->
wDay
=
Days_Per_Month_LY
[
13
-
lpSystemTime
->
wMonth
]
-
r
.
tm_mday
;
}
if
(
!
isleap
(
lpSystemTime
->
wYear
))
{
/*
(Century_Code+Month_Code+Year_Code+Day) % 7
The century code repeats every 400 years , so the array
works out like this,
Century_Code[0] is for 16th/20th Centry
Century_Code[1] is for 17th/21th Centry
Century_Code[2] is for 18th/22th Centry
Century_Code[3] is for 19th/23th Centry
The year code is found with the formula (year + (year / 4))
the "year" must be between 0 and 99 .
The Month Code (Month_Code[1]) starts with January and
ends with December.
*/
lpSystemTime
->
wDayOfWeek
=
(
Century_Code
[((
(
lpSystemTime
->
wYear
+
100
)
-
lpSystemTime
->
wYear
%
100
)
/
100
)
%
4
]
+
((
lpSystemTime
->
wYear
%
100
)
+
(
lpSystemTime
->
wYear
%
100
)
/
4
)
+
Month_Code
[
lpSystemTime
->
wMonth
]
+
lpSystemTime
->
wDay
)
%
7
;
if
(
lpSystemTime
->
wDayOfWeek
==
0
)
lpSystemTime
->
wDayOfWeek
=
7
;
else
lpSystemTime
->
wDayOfWeek
-=
1
;
}
else
{
lpSystemTime
->
wDayOfWeek
=
(
Century_Code
[(((
lpSystemTime
->
wYear
+
100
)
-
lpSystemTime
->
wYear
%
100
)
/
100
)
%
4
]
+
((
lpSystemTime
->
wYear
%
100
)
+
(
lpSystemTime
->
wYear
%
100
)
/
4
)
+
Month_Code_LY
[
lpSystemTime
->
wMonth
]
+
lpSystemTime
->
wDay
)
%
7
;
if
(
lpSystemTime
->
wDayOfWeek
==
0
)
lpSystemTime
->
wDayOfWeek
=
7
;
else
lpSystemTime
->
wDayOfWeek
-=
1
;
}
t
=
floor
(
vtime
);
timeofday
=
vtime
-
t
;
lpSystemTime
->
wMilliseconds
=
(
timeofday
-
lpSystemTime
->
wHour
*
(
1
/
24
)
-
lpSystemTime
->
wMinute
*
(
1
/
1440
)
-
lpSystemTime
->
wSecond
*
(
1
/
86400
)
)
*
(
1
/
5184000
);
return
1
;
}
/***********************************************************************
* VarUdateFromDate [OLEAUT32.331]
*/
HRESULT
WINAPI
VarUdateFromDate
(
DATE
datein
,
ULONG
dwFlags
,
UDATE
*
pudateout
)
{
HRESULT
i
=
0
;
static
const
BYTE
Days_Per_Month
[]
=
{
0
,
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
};
static
const
BYTE
Days_Per_Month_LY
[]
=
{
0
,
31
,
29
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
};
TRACE
(
"DATE = %f
\n
"
,
(
double
)
datein
);
i
=
VariantTimeToSystemTime
(
datein
,
&
(
pudateout
->
st
)
);
if
(
i
)
{
pudateout
->
wDayOfYear
=
0
;
if
(
isleap
(
pudateout
->
st
.
wYear
))
{
for
(
i
=
1
;
i
<
pudateout
->
st
.
wMonth
;
i
++
)
pudateout
->
wDayOfYear
+=
Days_Per_Month
[
i
];
}
else
{
for
(
i
=
1
;
i
<
pudateout
->
st
.
wMonth
;
i
++
)
pudateout
->
wDayOfYear
+=
Days_Per_Month_LY
[
i
];
}
pudateout
->
wDayOfYear
+=
pudateout
->
st
.
wDay
;
dwFlags
=
0
;
/*VAR_VALIDDATE*/
}
else
dwFlags
=
0
;
return
i
;
}
/***********************************************************************
* VarDateFromUdate [OLEAUT32.330]
*/
HRESULT
WINAPI
VarDateFromUdate
(
UDATE
*
pudateout
,
ULONG
dwFlags
,
DATE
*
datein
)
{
HRESULT
i
;
double
t
=
0
;
TRACE
(
" %d/%d/%d %d:%d:%d
\n
"
,
pudateout
->
st
.
wMonth
,
pudateout
->
st
.
wDay
,
pudateout
->
st
.
wYear
,
pudateout
->
st
.
wHour
,
pudateout
->
st
.
wMinute
,
pudateout
->
st
.
wSecond
);
i
=
SystemTimeToVariantTime
(
&
(
pudateout
->
st
),
&
t
);
*
datein
=
t
;
if
(
i
)
return
S_OK
;
else
return
E_INVALIDARG
;
}
/**********************************************************************
* VarBstrCmp [OLEAUT32.314]
*
* flags can be:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment