diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c index 18da8e4991f..1d3929ba249 100644 --- a/dlls/vbscript/global.c +++ b/dlls/vbscript/global.c @@ -2205,10 +2205,67 @@ static HRESULT Global_GetObject(BuiltinDisp *This, VARIANT *args, unsigned args_ return hres; } -static HRESULT Global_DateAdd(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) +static HRESULT Global_DateAdd(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) { - FIXME("\n"); - return E_NOTIMPL; + BSTR interval = NULL; + UDATE ud = {{ 0 }}; + HRESULT hres; + double date; + int count; + + TRACE("\n"); + + assert(args_cnt == 3); + + if (V_VT(args) == VT_NULL || V_VT(args + 1) == VT_NULL) + return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE); + + if (V_VT(args + 2) == VT_NULL) + return return_null(res); + + hres = to_string(args, &interval); + if (SUCCEEDED(hres)) + hres = to_int(args + 1, &count); + if (SUCCEEDED(hres)) + hres = to_system_time(args + 2, &ud.st); + if (SUCCEEDED(hres)) + { + if (!wcsicmp(interval, L"yyyy")) + ud.st.wYear += count; + else if (!wcsicmp(interval, L"q")) + ud.st.wMonth += 3 * count; + else if (!wcsicmp(interval, L"m")) + ud.st.wMonth += count; + else if (!wcsicmp(interval, L"y") + || !wcsicmp(interval, L"d") + || !wcsicmp(interval, L"w")) + { + ud.st.wDay += count; + } + else if (!wcsicmp(interval, L"ww")) + ud.st.wDay += 7 * count; + else if (!wcsicmp(interval, L"h")) + ud.st.wHour += count; + else if (!wcsicmp(interval, L"n")) + ud.st.wMinute += count; + else if (!wcsicmp(interval, L"s")) + ud.st.wSecond += count; + else + { + WARN("Unrecognized interval %s.\n", debugstr_w(interval)); + hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL); + } + } + + SysFreeString(interval); + + if (SUCCEEDED(hres)) + hres = VarDateFromUdateEx(&ud, 0, 0, &date); + + if (SUCCEEDED(hres)) + hres = return_date(res, date); + + return hres; } static HRESULT Global_DateDiff(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) diff --git a/dlls/vbscript/tests/api.vbs b/dlls/vbscript/tests/api.vbs index 3bc64d74193..a765eb1fcda 100644 --- a/dlls/vbscript/tests/api.vbs +++ b/dlls/vbscript/tests/api.vbs @@ -1988,4 +1988,52 @@ call testDateSerial(2000, 14, 2, 2001, 2, 2) call testDateSerial(9999, 12, 1, 9999, 12, 1) call testDateSerialError() +sub testDateAdd(d, interval, number, expected_date) + dim x + x = DateAdd(interval, number, d) + call ok(Year(x) = Year(expected_date), "year = " & Year(x) & " expected " & Year(expected_date)) + call ok(Month(x) = Month(expected_date), "month = " & Month(x) & " expected " & Month(expected_date)) + call ok(Day(x) = Day(expected_date), "day = " & Day(x) & " expected " & Day(expected_date)) + call ok(getVT(x) = "VT_DATE*", "getVT = " & getVT(x)) +end sub + +sub testDateAddError() + on error resume next + dim x + call Err.clear() + x = DateAdd("k", 1, DateSerial(2000, 2, 1)) + call ok(Err.number = 5, "Err.number = " & Err.number) + call ok(getVT(x) = "VT_EMPTY*", "getVT = " & getVT(x)) + call Err.clear() + call DateAdd(null, 1, DateSerial(2000, 2, 1)) + call ok(Err.number = 94, "Err.number = " & Err.number) + call Err.clear() + call DateAdd("q", null, DateSerial(2000, 2, 1)) + call ok(Err.number = 94, "Err.number = " & Err.number) + call Err.clear() + x = DateAdd("q", 1, null) + call ok(getVT(x) = "VT_NULL*", "getVT = " & getVT(x)) + call ok(Err.number = 0, "Err.number = " & Err.number) +end sub + +call testDateAdd(DateSerial(2000, 1, 1), "yyyy", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 1, 1), "yYyy", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 1, 1), "q", 1, DateSerial(2000, 4, 1)) +call testDateAdd(DateSerial(2000, 1, 1), "Q", 1, DateSerial(2000, 4, 1)) +call testDateAdd(DateSerial(2000, 1, 1), "m", -1, DateSerial(1999, 12, 1)) +call testDateAdd(DateSerial(2000, 1, 1), "M", -1, DateSerial(1999, 12, 1)) +call testDateAdd(DateSerial(2000, 12, 31), "y", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 12, 31), "Y", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 12, 31), "d", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 12, 31), "D", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 12, 31), "w", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 12, 31), "W", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 1, 1), "y", -1, DateSerial(1999, 12, 31)) +call testDateAdd(DateSerial(2000, 1, 1), "d", -1, DateSerial(1999, 12, 31)) +call testDateAdd(DateSerial(2000, 1, 1), "w", -1, DateSerial(1999, 12, 31)) +call testDateAdd(DateSerial(2000, 1, 1), "ww", 1, DateSerial(2000, 1, 8)) +call testDateAdd(DateSerial(2000, 1, 1), "ww", -1, DateSerial(1999, 12, 25)) +call testDateAdd(DateSerial(2000, 1, 1), "Ww", -1, DateSerial(1999, 12, 25)) +call testDateAddError() + Call reportSuccess()