jscript: Added DateConstr_parse implementation.

This commit is contained in:
Piotr Caban 2009-07-06 11:00:22 +02:00 committed by Alexandre Julliard
parent c3e66a8f86
commit 45817bf50f
3 changed files with 299 additions and 2 deletions

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
* Copyright 2009 Piotr Caban
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -2205,11 +2206,290 @@ static HRESULT create_date(script_ctx_t *ctx, BOOL use_constr, DOUBLE time, Disp
return S_OK;
}
static inline HRESULT date_parse(BSTR input, VARIANT *retv) {
static const DWORD string_ids[] = { LOCALE_SMONTHNAME12, LOCALE_SMONTHNAME11,
LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME8,
LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME5,
LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME2,
LOCALE_SMONTHNAME1, LOCALE_SDAYNAME7, LOCALE_SDAYNAME1,
LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
LOCALE_SDAYNAME5, LOCALE_SDAYNAME6 };
BSTR strings[sizeof(string_ids)/sizeof(DWORD)];
BSTR parse;
int input_len, parse_len = 0, nest_level = 0, i, size;
int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0;
int ms = 0, offset = 0, hour_adjust = 0;
BOOL set_year = FALSE, set_month = FALSE, set_day = FALSE, set_hour = FALSE;
BOOL set_offset = FALSE, set_era = FALSE, ad = TRUE, set_am = FALSE, am = TRUE;
BOOL set_hour_adjust = TRUE;
TIME_ZONE_INFORMATION tzi;
DateInstance di;
DWORD lcid_en;
if(retv) num_set_nan(retv);
input_len = SysStringLen(input);
for(i=0; i<input_len; i++) {
if(input[i] == '(') nest_level++;
else if(input[i] == ')') {
nest_level--;
if(nest_level<0)
return S_OK;
}
else if(!nest_level) parse_len++;
}
parse = SysAllocStringLen(NULL, parse_len);
if(!parse)
return E_OUTOFMEMORY;
nest_level = 0;
parse_len = 0;
for(i=0; i<input_len; i++) {
if(input[i] == '(') nest_level++;
else if(input[i] == ')') nest_level--;
else if(!nest_level) parse[parse_len++] = toupperW(input[i]);
}
GetTimeZoneInformation(&tzi);
di.bias = tzi.Bias;
di.standardDate = tzi.StandardDate;
di.standardBias = tzi.StandardBias;
di.daylightDate = tzi.DaylightDate;
di.daylightBias = tzi.DaylightBias;
lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
for(i=0; i<sizeof(string_ids)/sizeof(DWORD); i++) {
size = GetLocaleInfoW(lcid_en, string_ids[i], NULL, 0);
strings[i] = SysAllocStringLen(NULL, size);
if(!strings[i]) {
i--;
while(i-- >= 0)
SysFreeString(strings[i]);
SysFreeString(parse);
return E_OUTOFMEMORY;
}
GetLocaleInfoW(lcid_en, string_ids[i], strings[i], size);
}
for(i=0; i<parse_len;) {
while(isspaceW(parse[i])) i++;
if(parse[i] == ',') {
while(parse[i] == ',') i++;
continue;
}
if(parse[i]>='0' && parse[i]<='9') {
int tmp = atoiW(&parse[i]);
while(parse[i]>='0' && parse[i]<='9') i++;
while(isspaceW(parse[i])) i++;
if(parse[i] == ':') {
/* Time */
if(set_hour) break;
set_hour = TRUE;
hour = tmp;
while(parse[i] == ':') i++;
while(isspaceW(parse[i])) i++;
if(parse[i]>='0' && parse[i]<='9') {
min = atoiW(&parse[i]);
while(parse[i]>='0' && parse[i]<='9') i++;
}
while(isspaceW(parse[i])) i++;
while(parse[i] == ':') i++;
while(isspaceW(parse[i])) i++;
if(parse[i]>='0' && parse[i]<='9') {
sec = atoiW(&parse[i]);
while(parse[i]>='0' && parse[i]<='9') i++;
}
}
else if(parse[i]=='-' || parse[i]=='/') {
/* Short date */
if(set_day || set_month || set_year) break;
set_day = TRUE;
set_month = TRUE;
set_year = TRUE;
month = tmp-1;
while(isspaceW(parse[i])) i++;
while(parse[i]=='-' || parse[i]=='/') i++;
while(isspaceW(parse[i])) i++;
if(parse[i]<'0' || parse[i]>'9') break;
day = atoiW(&parse[i]);
while(parse[i]>='0' && parse[i]<='9') i++;
while(parse[i]=='-' || parse[i]=='/') i++;
while(isspaceW(parse[i])) i++;
if(parse[i]<'0' || parse[i]>'9') break;
year = atoiW(&parse[i]);
while(parse[i]>='0' && parse[i]<='9') i++;
}
else if(tmp<0) break;
else if(tmp<70) {
/* Day */
if(set_day) break;
set_day = TRUE;
day = tmp;
}
else {
/* Year */
if(set_year) break;
set_year = TRUE;
year = tmp;
}
}
else {
if(parse[i]<'A' || parse[i]>'Z') break;
else if(parse[i]=='B' && (parse[i+1]=='C' ||
(parse[i+1]=='.' && parse[i+2]=='C'))) {
/* AD/BC */
if(set_era) break;
set_era = TRUE;
ad = FALSE;
i++;
if(parse[i] == '.') i++;
i++;
if(parse[i] == '.') i++;
}
else if(parse[i]=='A' && (parse[i+1]=='D' ||
(parse[i+1]=='.' && parse[i+2]=='D'))) {
/* AD/BC */
if(set_era) break;
set_era = TRUE;
i++;
if(parse[i] == '.') i++;
i++;
if(parse[i] == '.') i++;
}
else if(parse[i+1]<'A' || parse[i+1]>'Z') {
/* Timezone */
if(set_offset) break;
set_offset = TRUE;
if(parse[i] <= 'I') hour_adjust = parse[i]-'A'+2;
else if(parse[i] == 'J') break;
else if(parse[i] <= 'M') hour_adjust = parse[i]-'K'+11;
else if(parse[i] <= 'Y') hour_adjust = parse[i]-'N';
else hour_adjust = 1;
i++;
if(parse[i] == '.') i++;
}
else if(parse[i]=='A' && parse[i+1]=='M') {
/* AM/PM */
if(set_am) break;
set_am = TRUE;
am = TRUE;
i += 2;
}
else if(parse[i]=='P' && parse[i+1]=='M') {
/* AM/PM */
if(set_am) break;
set_am = TRUE;
am = FALSE;
i += 2;
}
else if((parse[i]=='U' && parse[i+1]=='T' && parse[i+2]=='C')
|| (parse[i]=='G' && parse[i+1]=='M' && parse[i+2]=='T')) {
/* Timezone */
BOOL positive = TRUE;
if(set_offset) break;
set_offset = TRUE;
set_hour_adjust = FALSE;
i += 3;
while(isspaceW(parse[i])) i++;
if(parse[i] == '-') positive = FALSE;
else if(parse[i] != '+') continue;
i++;
while(isspaceW(parse[i])) i++;
if(parse[i]<'0' || parse[i]>'9') break;
offset = atoiW(&parse[i]);
while(parse[i]>='0' && parse[i]<='9') i++;
if(offset<24) offset *= 60;
else offset = (offset/100)*60 + offset%100;
if(positive) offset = -offset;
}
else {
/* Month or garbage */
int j;
for(size=i; parse[size]>='A' && parse[size]<='Z'; size++);
size -= i;
for(j=0; j<sizeof(string_ids)/sizeof(DWORD); j++)
if(!memicmpW(&parse[i], strings[j], size)) break;
if(j < 12) {
if(set_month) break;
set_month = TRUE;
month = 11-j;
}
else if(j == sizeof(string_ids)/sizeof(DWORD)) break;
i += size;
}
}
}
if(retv && i==parse_len && set_year && set_month
&& set_day && (!set_am || hour<13)) {
if(set_am) {
if(hour == 12) hour = 0;
if(!am) hour += 12;
}
if(!ad) year = -year+1;
else if(year<100) year += 1900;
V_VT(retv) = VT_R8;
V_R8(retv) = time_clip(make_date(make_day(year, month, day),
make_time(hour+hour_adjust, min, sec, ms)) + offset*MS_PER_MINUTE);
if(set_hour_adjust) V_R8(retv) = utc(V_R8(retv), &di);
}
for(i=0; i<sizeof(string_ids)/sizeof(DWORD); i++)
SysFreeString(strings[i]);
SysFreeString(parse);
return S_OK;
}
static HRESULT DateConstr_parse(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FIXME("\n");
return E_NOTIMPL;
VARIANT prim;
HRESULT hres;
TRACE("\n");
if(!arg_cnt(dp)) {
if(retv)
num_set_nan(retv);
return S_OK;
}
hres = to_primitive(dispex->ctx, get_arg(dp,0), ei, &prim);
if(FAILED(hres))
return hres;
if(V_VT(&prim) != VT_BSTR) {
if(retv)
num_set_nan(retv);
return S_OK;
}
return date_parse(V_BSTR(&prim), retv);
}
static HRESULT DateConstr_UTC(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Jacek Caban for CodeWeavers
* Copyright 2009 Piotr Caban
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@ -1022,6 +1022,22 @@ ok(date.getTime() === 60987050010, "date.getTime() = " + date.getTime());
date.setUTCFullYear(83, 21, 321);
ok(date.getTime() === -59464984149990, "date.getTime() = " + date.getTime());
ok(isNaN(Date.parse()), "Date.parse() is not NaN");
ok(isNaN(Date.parse("")), "Date.parse(\"\") is not NaN");
ok(isNaN(Date.parse("Jan Jan 20 2009")), "Date.parse(\"Jan Jan 20 2009\") is not NaN");
ok(Date.parse("Jan 20 2009 UTC") === 1232409600000, "Date.parse(\"Jan 20 2009 UTC\") = " + Date.parse("Jan 20 2009 UTC"));
ok(Date.parse("Jan 20 2009 GMT") === 1232409600000, "Date.parse(\"Jan 20 2009 GMT\") = " + Date.parse("Jan 20 2009 GMT"));
ok(Date.parse("Jan 20 2009 UTC-0") === 1232409600000, "Date.parse(\"Jan 20 2009 UTC-0\") = " + Date.parse("Jan 20 2009 UTC-0"));
ok(Date.parse("Jan 20 2009 UTC+0000") === 1232409600000, "Date.parse(\"Jan 20 2009 UTC+0000\") = " + Date.parse("Jan 20 2009 UTC+0000"));
ok(Date.parse("Ju 13 79 UTC") === 300672000000, "Date.parse(\"Ju 13 79 UTC\") = " + Date.parse("Ju 13 79 UTC"));
ok(Date.parse("12Au91 UTC") === 681955200000, "Date.parse(\"12Au91 UTC\") = " + Date.parse("12Au91 UTC"));
ok(Date.parse("7/02/17 UTC") === -1656806400000, "Date.parse(\"7/02/17 UTC\") = " + Date.parse("7/02/17 UTC"));
ok(Date.parse("Se001 70 12:31:17 UTC") === 21040277000, "Date.parse(\"Se001 70 12:31:17 UTC\") = " + Date.parse("Se001 70 12:31:17 UTC"));
ok(Date.parse("February 31 UTC, 2000 12:31:17 PM") === 952000277000,
"Date.parse(\"February 31 UTC, 2000 12:31:17 PM\") = " + Date.parse("February 31 UTC, 2000 12:31:17 PM"));
ok(Date.parse("71 11:32AM Dec 12 UTC BC ") === -64346358480000, "Date.parse(\"71 11:32AM Dec 12 UTC BC \") = " + Date.parse("71 11:32AM Dec 12 UTC BC "));
ok(Date.parse("23/71/2000 11::32::UTC") === 1010662320000, "Date.parse(\"23/71/2000 11::32::UTC\") = " + Date.parse("23/71/2000 11::32::UTC"));
ok(typeof(Math.PI) === "number", "typeof(Math.PI) = " + typeof(Math.PI));
ok(Math.floor(Math.PI*100) === 314, "Math.PI = " + Math.PI);
Math.PI = "test";