Added VarDateFromStr API.
This commit is contained in:
parent
506115b8c5
commit
9c7c8a4a36
|
@ -16,6 +16,7 @@ C_SRCS = \
|
|||
oledlg.c \
|
||||
oleobj.c \
|
||||
olesvr.c \
|
||||
parsedt.c \
|
||||
storage.c \
|
||||
typelib.c \
|
||||
variant.c
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,374 @@
|
|||
/*
|
||||
PostgreSQL Data Base Management System (formerly known as Postgres, then
|
||||
as Postgres95).
|
||||
|
||||
Copyright (c) 1994-7 Regents of the University of California
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose, without fee, and without a written agreement
|
||||
is hereby granted, provided that the above copyright notice and this
|
||||
paragraph and the following two paragraphs appear in all copies.
|
||||
|
||||
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
|
||||
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
|
||||
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
|
||||
DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
|
||||
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* dt.h--
|
||||
* Definitions for the date/time and other date/time support code.
|
||||
* The support code is shared with other date data types,
|
||||
* including abstime, reltime, date, and time.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef DT_H
|
||||
#define DT_H
|
||||
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
/* We have to include stdlib.h here because it defines many of these macros
|
||||
on some platforms, and we only want our definitions used if stdlib.h doesn't
|
||||
have its own.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Section 1: bool, true, false, TRUE, FALSE
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
/*
|
||||
* bool --
|
||||
* Boolean value, either true or false.
|
||||
*
|
||||
*/
|
||||
#define false ((char) 0)
|
||||
#define true ((char) 1)
|
||||
#ifndef __cplusplus
|
||||
#ifndef bool
|
||||
typedef char bool;
|
||||
#endif /* ndef bool */
|
||||
#endif /* not C++ */
|
||||
typedef bool *BoolPtr;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif /* TRUE */
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif /* FALSE */
|
||||
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Section 3: standard system types
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* intN --
|
||||
* Signed integer, EXACTLY N BITS IN SIZE,
|
||||
* used for numerical computations and the
|
||||
* frontend/backend protocol.
|
||||
*/
|
||||
typedef signed char int8; /* == 8 bits */
|
||||
typedef signed short int16; /* == 16 bits */
|
||||
typedef signed int int32; /* == 32 bits */
|
||||
|
||||
/*
|
||||
* uintN --
|
||||
* Unsigned integer, EXACTLY N BITS IN SIZE,
|
||||
* used for numerical computations and the
|
||||
* frontend/backend protocol.
|
||||
*/
|
||||
typedef unsigned char uint8; /* == 8 bits */
|
||||
typedef unsigned short uint16; /* == 16 bits */
|
||||
typedef unsigned int uint32; /* == 32 bits */
|
||||
|
||||
/*
|
||||
* floatN --
|
||||
* Floating point number, AT LEAST N BITS IN SIZE,
|
||||
* used for numerical computations.
|
||||
*
|
||||
* Since sizeof(floatN) may be > sizeof(char *), always pass
|
||||
* floatN by reference.
|
||||
*/
|
||||
typedef float float32data;
|
||||
typedef double float64data;
|
||||
typedef float *float32;
|
||||
typedef double *float64;
|
||||
|
||||
/*
|
||||
* boolN --
|
||||
* Boolean value, AT LEAST N BITS IN SIZE.
|
||||
*/
|
||||
typedef uint8 bool8; /* >= 8 bits */
|
||||
typedef uint16 bool16; /* >= 16 bits */
|
||||
typedef uint32 bool32; /* >= 32 bits */
|
||||
|
||||
|
||||
/* Date/Time Configuration
|
||||
*
|
||||
* Constants to pass info from runtime environment:
|
||||
* USE_POSTGRES_DATES specifies traditional postgres format for output.
|
||||
* USE_ISO_DATES specifies ISO-compliant format for output.
|
||||
* USE_SQL_DATES specified Oracle/Ingres-compliant format for output.
|
||||
* USE_GERMAN_DATES specifies German-style dd.mm/yyyy date format.
|
||||
*
|
||||
* DateStyle specifies preference for date formatting for output.
|
||||
* EuroDates if client prefers dates interpreted and written w/European conventions.
|
||||
*
|
||||
* HasCTZSet if client timezone is specified by client.
|
||||
* CDayLight is the apparent daylight savings time status.
|
||||
* CTimeZone is the timezone offset in seconds.
|
||||
* CTZName is the timezone label.
|
||||
*/
|
||||
|
||||
#define USE_POSTGRES_DATES 0
|
||||
#define USE_ISO_DATES 1
|
||||
#define USE_SQL_DATES 2
|
||||
#define USE_GERMAN_DATES 3
|
||||
|
||||
int DateStyle;
|
||||
bool EuroDates;
|
||||
int CTimeZone;
|
||||
|
||||
typedef double float8;
|
||||
|
||||
struct varlena
|
||||
{
|
||||
int vl_len;
|
||||
char vl_dat[1];
|
||||
};
|
||||
|
||||
typedef struct varlena text;
|
||||
|
||||
|
||||
|
||||
typedef int AbsoluteTime;
|
||||
typedef int RelativeTime;
|
||||
|
||||
/*
|
||||
* 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)))
|
||||
|
||||
/*
|
||||
* DateTime represents absolute time.
|
||||
* TimeSpan represents delta time. Keep track of months (and years)
|
||||
* separately since the elapsed time spanned is unknown until instantiated
|
||||
* relative to an absolute time.
|
||||
*
|
||||
* Note that Postgres uses "time interval" to mean a bounded interval,
|
||||
* consisting of a beginning and ending time, not a time span - thomas 97/03/20
|
||||
*/
|
||||
|
||||
typedef double DateTime;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double time; /* all time units other than months and
|
||||
* years */
|
||||
int month; /* months and years, after time for
|
||||
* alignment */
|
||||
} TimeSpan;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* time types + support macros
|
||||
*
|
||||
* String definitions for standard time quantities.
|
||||
*
|
||||
* These strings are the defaults used to form output time strings.
|
||||
* Other alternate forms are hardcoded into token tables in dt.c.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define DAGO "ago"
|
||||
#define DCURRENT "current"
|
||||
#define EPOCH "epoch"
|
||||
#define INVALID "invalid"
|
||||
#define EARLY "-infinity"
|
||||
#define LATE "infinity"
|
||||
#define NOW "now"
|
||||
#define TODAY "today"
|
||||
#define TOMORROW "tomorrow"
|
||||
#define YESTERDAY "yesterday"
|
||||
#define ZULU "zulu"
|
||||
|
||||
#define DMICROSEC "usecond"
|
||||
#define DMILLISEC "msecond"
|
||||
#define DSECOND "second"
|
||||
#define DMINUTE "minute"
|
||||
#define DHOUR "hour"
|
||||
#define DDAY "day"
|
||||
#define DWEEK "week"
|
||||
#define DMONTH "month"
|
||||
#define DQUARTER "quarter"
|
||||
#define DYEAR "year"
|
||||
#define DDECADE "decade"
|
||||
#define DCENTURY "century"
|
||||
#define DMILLENIUM "millenium"
|
||||
#define DA_D "ad"
|
||||
#define DB_C "bc"
|
||||
#define DTIMEZONE "timezone"
|
||||
|
||||
/*
|
||||
* Fundamental time field definitions for parsing.
|
||||
*
|
||||
* Meridian: am, pm, or 24-hour style.
|
||||
* Millenium: ad, bc
|
||||
*/
|
||||
|
||||
#define AM 0
|
||||
#define PM 1
|
||||
#define HR24 2
|
||||
|
||||
#define AD 0
|
||||
#define BC 1
|
||||
|
||||
/*
|
||||
* Fields for time decoding.
|
||||
* Can't have more of these than there are bits in an unsigned int
|
||||
* since these are turned into bit masks during parsing and decoding.
|
||||
*/
|
||||
|
||||
#define RESERV 0
|
||||
#define MONTH 1
|
||||
#define YEAR 2
|
||||
#define DAY 3
|
||||
#define TIMES 4 /* not used - thomas 1997-07-14 */
|
||||
#define TZ 5
|
||||
#define DTZ 6
|
||||
#define DTZMOD 7
|
||||
#define IGNOREFIELD 8
|
||||
#define AMPM 9
|
||||
#define HOUR 10
|
||||
#define MINUTE 11
|
||||
#define SECOND 12
|
||||
#define DOY 13
|
||||
#define DOW 14
|
||||
#define UNITS 15
|
||||
#define ADBC 16
|
||||
/* these are only for relative dates */
|
||||
#define AGO 17
|
||||
#define ABS_BEFORE 18
|
||||
#define ABS_AFTER 19
|
||||
|
||||
/*
|
||||
* Token field definitions for time parsing and decoding.
|
||||
* These need to fit into the datetkn table type.
|
||||
* At the moment, that means keep them within [-127,127].
|
||||
* These are also used for bit masks in DecodeDateDelta()
|
||||
* so actually restrict them to within [0,31] for now.
|
||||
* - thomas 97/06/19
|
||||
* Not all of these fields are used for masks in DecodeDateDelta
|
||||
* so allow some larger than 31. - thomas 1997-11-17
|
||||
*/
|
||||
|
||||
#define DTK_NUMBER 0
|
||||
#define DTK_STRING 1
|
||||
|
||||
#define DTK_DATE 2
|
||||
#define DTK_TIME 3
|
||||
#define DTK_TZ 4
|
||||
#define DTK_AGO 5
|
||||
|
||||
#define DTK_SPECIAL 6
|
||||
#define DTK_INVALID 7
|
||||
#define DTK_CURRENT 8
|
||||
#define DTK_EARLY 9
|
||||
#define DTK_LATE 10
|
||||
#define DTK_EPOCH 11
|
||||
#define DTK_NOW 12
|
||||
#define DTK_YESTERDAY 13
|
||||
#define DTK_TODAY 14
|
||||
#define DTK_TOMORROW 15
|
||||
#define DTK_ZULU 16
|
||||
|
||||
#define DTK_DELTA 17
|
||||
#define DTK_SECOND 18
|
||||
#define DTK_MINUTE 19
|
||||
#define DTK_HOUR 20
|
||||
#define DTK_DAY 21
|
||||
#define DTK_WEEK 22
|
||||
#define DTK_MONTH 23
|
||||
#define DTK_QUARTER 24
|
||||
#define DTK_YEAR 25
|
||||
#define DTK_DECADE 26
|
||||
#define DTK_CENTURY 27
|
||||
#define DTK_MILLENIUM 28
|
||||
#define DTK_MILLISEC 29
|
||||
#define DTK_MICROSEC 30
|
||||
|
||||
#define DTK_DOW 32
|
||||
#define DTK_DOY 33
|
||||
#define DTK_TZ_HOUR 34
|
||||
#define DTK_TZ_MINUTE 35
|
||||
|
||||
/*
|
||||
* Bit mask definitions for time parsing.
|
||||
*/
|
||||
|
||||
#define DTK_M(t) (0x01 << (t))
|
||||
|
||||
#define DTK_DATE_M (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))
|
||||
#define DTK_TIME_M (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_M(SECOND))
|
||||
|
||||
#define MAXDATELEN 47 /* maximum possible length of an input
|
||||
* date string */
|
||||
#define MAXDATEFIELDS 25 /* maximum possible number of fields in a
|
||||
* date string */
|
||||
#define TOKMAXLEN 10 /* only this many chars are stored in
|
||||
* datetktbl */
|
||||
|
||||
/* keep this struct small; it gets used a lot */
|
||||
typedef struct
|
||||
{
|
||||
#if defined(_AIX)
|
||||
char *token;
|
||||
#else
|
||||
char token[TOKMAXLEN];
|
||||
#endif /* _AIX */
|
||||
char type;
|
||||
char value; /* this may be unsigned, alas */
|
||||
} datetkn;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* dt.c prototypes
|
||||
*/
|
||||
|
||||
|
||||
void j2date(int jd, int *year, int *month, int *day);
|
||||
int date2j(int year, int month, int day);
|
||||
|
||||
int ParseDateTime(char *timestr, char *lowstr,
|
||||
char **field, int *ftype, int maxfields, int *numfields);
|
||||
int DecodeDateTime(char **field, int *ftype,
|
||||
int nf, int *dtype, struct tm * tm, double *fsec, int *tzp);
|
||||
|
||||
int DecodeTimeOnly(char **field, int *ftype, int nf,
|
||||
int *dtype, struct tm * tm, double *fsec);
|
||||
|
||||
|
||||
#endif /* DT_H */
|
525
ole/variant.c
525
ole/variant.c
|
@ -15,8 +15,9 @@
|
|||
* - The Variant APIs do not the following types: IUknown, IDispatch, DECIMAL and SafeArray.
|
||||
* The prototypes for these are commented out in the oleauto.h file. They need
|
||||
* to be implemented and cases need to be added to the switches of the existing APIs.
|
||||
* - The parsing of date for the VarDateFromStr still needs to be done. I'm currently
|
||||
* working on this.
|
||||
* - The parsing of date for the VarDateFromStr is not complete.
|
||||
* - The date manipulations do not support date prior to 1900.
|
||||
* - The parsing does not accept has many formats has the Windows implementation.
|
||||
*/
|
||||
|
||||
#include "wintypes.h"
|
||||
|
@ -25,6 +26,7 @@
|
|||
#include "debug.h"
|
||||
#include "winerror.h"
|
||||
#include "mapidefs.h"
|
||||
#include "parsedt.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -72,6 +74,391 @@ static const DATE DATE_MAX = 2958465;
|
|||
#define BUFFER_MAX 1024
|
||||
static char pBuffer[BUFFER_MAX];
|
||||
|
||||
/*
|
||||
* 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 postgeSQL 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.001
|
||||
* One + every 400 years: 1/400 -> 365.0025
|
||||
*/
|
||||
static const double DAYS_IN_ONE_YEAR = 365.2515;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* DateTimeStringToTm [INTERNAL]
|
||||
*
|
||||
* Converts a string representation of a date and/or time to a tm structure.
|
||||
*
|
||||
* Note this function uses the postgresql date parsing functions found
|
||||
* in the parsedt.c file.
|
||||
*
|
||||
* Returns TRUE if successfull.
|
||||
*
|
||||
* Note: This function does not parse the day of the week,
|
||||
* daylight savings time. It will only fill the followin fields in
|
||||
* the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
|
||||
*
|
||||
******************************************************************************/
|
||||
static BOOL32 DateTimeStringToTm( OLECHAR32* strIn, LCID lcid, struct tm* pTm )
|
||||
{
|
||||
BOOL32 res = FALSE;
|
||||
double fsec;
|
||||
int tzp;
|
||||
int dtype;
|
||||
int nf;
|
||||
char *field[MAXDATEFIELDS];
|
||||
int ftype[MAXDATEFIELDS];
|
||||
char lowstr[MAXDATELEN + 1];
|
||||
char* strDateTime = NULL;
|
||||
|
||||
/* Convert the string to ASCII since this is the only format
|
||||
* postgesql can handle.
|
||||
*/
|
||||
strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
|
||||
|
||||
if( strDateTime != NULL )
|
||||
{
|
||||
/* Make sure we don't go over the maximum length
|
||||
* accepted by postgesql.
|
||||
*/
|
||||
if( strlen( strDateTime ) <= MAXDATELEN )
|
||||
{
|
||||
if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
|
||||
{
|
||||
if( lcid & VAR_DATEVALUEONLY )
|
||||
{
|
||||
/* Get the date information.
|
||||
* It returns 0 if date information was
|
||||
* present and 1 if only time information was present.
|
||||
* -1 if an error occures.
|
||||
*/
|
||||
if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
|
||||
{
|
||||
/* Eliminate the time information since we
|
||||
* were asked to get date information only.
|
||||
*/
|
||||
pTm->tm_sec = 0;
|
||||
pTm->tm_min = 0;
|
||||
pTm->tm_hour = 0;
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
if( lcid & VAR_TIMEVALUEONLY )
|
||||
{
|
||||
/* Get time information only.
|
||||
*/
|
||||
if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
|
||||
{
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get both date and time information.
|
||||
* It returns 0 if date information was
|
||||
* present and 1 if only time information was present.
|
||||
* -1 if an error occures.
|
||||
*/
|
||||
if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
|
||||
{
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, strDateTime );
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 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 successfull.
|
||||
*/
|
||||
static BOOL32 TmToDATE( struct tm* pTm, DATE *pDateOut )
|
||||
{
|
||||
if( (pTm->tm_year - 1900) >= 0 )
|
||||
{
|
||||
int leapYear = 0;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* DateToTm [INTERNAL]
|
||||
*
|
||||
* This function converst 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 successfull.
|
||||
*/
|
||||
static BOOL32 DateToTm( DATE dateIn, LCID lcid, struct tm* pTm )
|
||||
{
|
||||
/* Do not process dates smaller than January 1, 1900.
|
||||
* Which corresponds to 2.0 in the windows DATE format.
|
||||
*/
|
||||
if( dateIn >= 2.0 )
|
||||
{
|
||||
double decimalPart = 0.0;
|
||||
double wholePart = 0.0;
|
||||
|
||||
pTm->tm_sec = 0;
|
||||
pTm->tm_min = 0;
|
||||
pTm->tm_hour = 0;
|
||||
pTm->tm_mday = 0;
|
||||
pTm->tm_mon = 0;
|
||||
pTm->tm_year = 0;
|
||||
pTm->tm_wday = 0;
|
||||
pTm->tm_yday = 0;
|
||||
pTm->tm_isdst = 0;
|
||||
pTm->tm_gmtoff = 0;
|
||||
pTm->tm_zone = 0;
|
||||
|
||||
/* Because of the nature of DATE format witch
|
||||
* 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 simplyfies the processing of the DATE value.
|
||||
*/
|
||||
dateIn -= 1.0;
|
||||
|
||||
wholePart = (double) floor( dateIn );
|
||||
decimalPart = fmod( dateIn, wholePart );
|
||||
|
||||
if( !(lcid & VAR_TIMEVALUEONLY) )
|
||||
{
|
||||
int nDay = 0;
|
||||
int leapYear = 0;
|
||||
double yearsSince1900 = 0;
|
||||
/* Start at 1900, this 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 );
|
||||
pTm->tm_year += yearsSince1900;
|
||||
/* determine if this is a leap year.
|
||||
*/
|
||||
if( isleap( pTm->tm_year ) )
|
||||
leapYear = 1;
|
||||
/* find what day of that year does 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 is must be converted from [1-366] to [0-365]
|
||||
*/
|
||||
//pTm->tm_yday = nDay - 1;
|
||||
/* find which mount 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( !(lcid & 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;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -2555,12 +2942,9 @@ HRESULT WINAPI VarDateFromI432(LONG lIn, DATE* pdateOut)
|
|||
*/
|
||||
HRESULT WINAPI VarDateFromR432(FLOAT fltIn, DATE* pdateOut)
|
||||
{
|
||||
unsigned long test = 0;
|
||||
|
||||
TRACE( ole, "( %f, %p ), stub\n", fltIn, pdateOut );
|
||||
|
||||
test = (unsigned long) fltIn;
|
||||
if( test < DATE_MIN || test > DATE_MAX )
|
||||
if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
|
||||
{
|
||||
return DISP_E_OVERFLOW;
|
||||
}
|
||||
|
@ -2575,12 +2959,9 @@ HRESULT WINAPI VarDateFromR432(FLOAT fltIn, DATE* pdateOut)
|
|||
*/
|
||||
HRESULT WINAPI VarDateFromR832(double dblIn, DATE* pdateOut)
|
||||
{
|
||||
unsigned long test = 0;
|
||||
|
||||
TRACE( ole, "( %f, %p ), stub\n", dblIn, pdateOut );
|
||||
|
||||
test = (unsigned long) dblIn;
|
||||
if( test < DATE_MIN || test > DATE_MAX )
|
||||
if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
|
||||
{
|
||||
return DISP_E_OVERFLOW;
|
||||
}
|
||||
|
@ -2618,8 +2999,22 @@ HRESULT WINAPI VarDateFromR832(double dblIn, DATE* pdateOut)
|
|||
HRESULT WINAPI VarDateFromStr32(OLECHAR32* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
|
||||
{
|
||||
HRESULT ret = S_OK;
|
||||
struct tm TM = { 0,0,0,0,0,0,0,0,0 };
|
||||
|
||||
TRACE( ole, "( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
|
||||
|
||||
if( DateTimeStringToTm( strIn, lcid, &TM ) )
|
||||
{
|
||||
if( TmToDATE( &TM, pdateOut ) == FALSE )
|
||||
{
|
||||
ret = E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = DISP_E_TYPEMISMATCH;
|
||||
}
|
||||
|
||||
FIXME( ole, "( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2780,7 +3175,7 @@ HRESULT WINAPI VarBstrFromR832(double dblIn, LCID lcid, ULONG dwFlags, BSTR32* p
|
|||
* 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 since 1900
|
||||
* 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
|
||||
|
@ -2788,105 +3183,13 @@ HRESULT WINAPI VarBstrFromR832(double dblIn, LCID lcid, ULONG dwFlags, BSTR32* p
|
|||
*/
|
||||
HRESULT WINAPI VarBstrFromDate32(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR32* pbstrOut)
|
||||
{
|
||||
/* If the date is not after the 1900 return an error because
|
||||
* the tm structure does not allow such dates.
|
||||
*/
|
||||
if( dateIn >= 1.0 )
|
||||
{
|
||||
double decimalPart = 0.0;
|
||||
double wholePart = 0.0;
|
||||
struct tm TM = {0,0,0,0,0,0,0,0,0};
|
||||
|
||||
wholePart = (double) (long) dateIn;
|
||||
decimalPart = fmod( dateIn, wholePart );
|
||||
TRACE( ole, "( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
|
||||
|
||||
if( !(lcid & VAR_TIMEVALUEONLY) )
|
||||
{
|
||||
int nDay = 0;
|
||||
int leapYear = 0;
|
||||
/* find in what year the day in the "wholePart" falls into.
|
||||
*/
|
||||
TM.tm_year = (int) ( wholePart / 365.25 );
|
||||
/* determine if this is a leap year.
|
||||
*/
|
||||
if( ( TM.tm_year % 4 ) == 0 )
|
||||
leapYear = 1;
|
||||
/* find what day of that year does the "wholePart" corresponds to.
|
||||
* the day is [1-366]
|
||||
*/
|
||||
nDay = (int) ( wholePart - ( TM.tm_year * 365.25 ) );
|
||||
TM.tm_yday = nDay - 1;
|
||||
/* find which mount this day corresponds to.
|
||||
*/
|
||||
if( nDay <= 31 )
|
||||
if( DateToTm( dateIn, lcid, &TM ) == FALSE )
|
||||
{
|
||||
TM.tm_mday = nDay;
|
||||
TM.tm_mon = 0;
|
||||
}
|
||||
else if( nDay <= ( 59 + leapYear ) )
|
||||
{
|
||||
TM.tm_mday = nDay - 31;
|
||||
TM.tm_mon = 1;
|
||||
}
|
||||
else if( nDay <= ( 90 + leapYear ) )
|
||||
{
|
||||
TM.tm_mday = nDay - ( 59 + leapYear );
|
||||
TM.tm_mon = 2;
|
||||
}
|
||||
else if( nDay <= ( 120 + leapYear ) )
|
||||
{
|
||||
TM.tm_mday = nDay - ( 90 + leapYear );
|
||||
TM.tm_mon = 3;
|
||||
}
|
||||
else if( nDay <= ( 151 + leapYear ) )
|
||||
{
|
||||
TM.tm_mday = nDay - ( 120 + leapYear );
|
||||
TM.tm_mon = 4;
|
||||
}
|
||||
else if( nDay <= ( 181 + leapYear ) )
|
||||
{
|
||||
TM.tm_mday = nDay - ( 151 + leapYear );
|
||||
TM.tm_mon = 5;
|
||||
}
|
||||
else if( nDay <= ( 212 + leapYear ) )
|
||||
{
|
||||
TM.tm_mday = nDay - ( 181 + leapYear );
|
||||
TM.tm_mon = 6;
|
||||
}
|
||||
else if( nDay <= ( 243 + leapYear ) )
|
||||
{
|
||||
TM.tm_mday = nDay - ( 212 + leapYear );
|
||||
TM.tm_mon = 7;
|
||||
}
|
||||
else if( nDay <= ( 273 + leapYear ) )
|
||||
{
|
||||
TM.tm_mday = nDay - ( 243 + leapYear );
|
||||
TM.tm_mon = 8;
|
||||
}
|
||||
else if( nDay <= ( 304 + leapYear ) )
|
||||
{
|
||||
TM.tm_mday = nDay - ( 273 + leapYear );
|
||||
TM.tm_mon = 9;
|
||||
}
|
||||
else if( nDay <= ( 334 + leapYear ) )
|
||||
{
|
||||
TM.tm_mday = nDay - ( 304 + leapYear );
|
||||
TM.tm_mon = 10;
|
||||
}
|
||||
else if( nDay <= ( 365 + leapYear ) )
|
||||
{
|
||||
TM.tm_mday = nDay - ( 334 + leapYear );
|
||||
TM.tm_mon = 11;
|
||||
}
|
||||
}
|
||||
if( !(lcid & VAR_DATEVALUEONLY) )
|
||||
{
|
||||
/* find the number of seconds in this day.
|
||||
* fractional part times, hours, minutes, seconds.
|
||||
*/
|
||||
TM.tm_hour = (int) ( decimalPart * 24 );
|
||||
TM.tm_min = (int) ( ( ( decimalPart * 24 ) - TM.tm_hour ) * 60 );
|
||||
TM.tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( TM.tm_hour * 60 ) - TM.tm_min ) * 60 );
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if( lcid & VAR_DATEVALUEONLY )
|
||||
|
@ -2894,15 +3197,9 @@ HRESULT WINAPI VarBstrFromDate32(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR32*
|
|||
else if( lcid & VAR_TIMEVALUEONLY )
|
||||
strftime( pBuffer, BUFFER_MAX, "%X", &TM );
|
||||
else
|
||||
strftime( pBuffer, 100, "%x %X", &TM );
|
||||
strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
|
||||
|
||||
*pbstrOut = StringDupAtoBstr( pBuffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME( ole, "( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue