diff --git a/dlls/oleaut32/tests/vartype.c b/dlls/oleaut32/tests/vartype.c index 4a32caae5c2..bf31fde2b7a 100644 --- a/dlls/oleaut32/tests/vartype.c +++ b/dlls/oleaut32/tests/vartype.c @@ -83,6 +83,8 @@ static BOOL has_locales; #define EXPECT(x) EXPECTRES(S_OK, (x)) #define EXPECT_DBL(x) \ ok(hres == S_OK && EQ_DOUBLE(out, (x)), "expected %.16g, got %.16g; hres=0x%08x\n", (x), out, hres) +#define EXPECT_DBL2(new,old) \ + ok(hres == S_OK && (EQ_DOUBLE(out, (new)) || broken(EQ_DOUBLE(out, (old)))), "expected %.16g or %.16g, got %.16g; hres=0x%08x\n", (new), (old), out, hres) #define CONVERT(func, val) in = val; hres = func(in, &out) #define CONVERTRANGE(func,start,end) for (i = start; i < end; i+=1) { CONVERT(func, i); EXPECT(i); }; @@ -3048,21 +3050,23 @@ static void test_VarDateFromStr(void) */ DFS("14 1"); MKRELDATE(14,1); EXPECT_DBL(relative); DFS("1 14"); EXPECT_DBL(relative); - /* If the numbers can't be day/month, they are assumed to be year/month */ - DFS("30 2"); EXPECT_DBL(10990.0); - DFS("2 30"); EXPECT_DBL(10990.0); + /* If the numbers can't be day/month, they are assumed to be year/month. + * But see the Y2K cutoff below. + */ + DFS("30 2"); EXPECT_DBL2(47515.0, 10990.0); + DFS("2 30"); EXPECT_DBL2(47515.0, 10990.0); DFS("32 49"); EXPECT_MISMATCH; /* Can't be any format */ DFS("0 49"); EXPECT_MISMATCH; /* Can't be any format */ /* If a month name is given the other number is the day */ DFS("Jan 2"); MKRELDATE(2,1); EXPECT_DBL(relative); DFS("2 Jan"); EXPECT_DBL(relative); /* Unless it can't be, in which case it becomes the year */ - DFS("Jan 35"); EXPECT_DBL(12785.0); - DFS("35 Jan"); EXPECT_DBL(12785.0); - DFS("Jan-35"); EXPECT_DBL(12785.0); - DFS("35-Jan"); EXPECT_DBL(12785.0); - DFS("Jan/35"); EXPECT_DBL(12785.0); - DFS("35/Jan"); EXPECT_DBL(12785.0); + DFS("Jan 35"); EXPECT_DBL2(49310.0, 12785.0); + DFS("35 Jan"); EXPECT_DBL2(49310.0, 12785.0); + DFS("Jan-35"); EXPECT_DBL2(49310.0, 12785.0); + DFS("35-Jan"); EXPECT_DBL2(49310.0, 12785.0); + DFS("Jan/35"); EXPECT_DBL2(49310.0, 12785.0); + DFS("35/Jan"); EXPECT_DBL2(49310.0, 12785.0); /* 3 elements */ /* 3 numbers and time separator => h:m:s */ DFS("0.1.0"); EXPECT_DBL(0.0006944444444444445); @@ -3072,12 +3076,21 @@ static void test_VarDateFromStr(void) DFS("14 2 3"); EXPECT_DBL(41673.0); DFS("2 14 3"); EXPECT_DBL(37666.0); DFS("2 3 14"); EXPECT_DBL(41673.0); - DFS("32 2 3"); EXPECT_DBL(11722.0); - DFS("2 3 32"); EXPECT_DBL(11722.0); - DFS("1 2 29"); EXPECT_DBL(47120.0); - /* After 30, two digit dates are expected to be in the 1900's */ - DFS("1 2 30"); EXPECT_DBL(10960.0); - DFS("1 2 31"); EXPECT_DBL(11325.0); + DFS("32 2 3"); EXPECT_DBL2(48247.0, 11722.0); + DFS("2 3 32"); EXPECT_DBL2(48247.0, 11722.0); + + /* Old Windows versions use 29 as the Y2K cutoff: + * years 00-29 map to 2000-2029 while years 30-99 map to 1930-1999 + */ + DFS("1 1 0"); EXPECT_DBL(36526.0); + DFS("12 31 29"); EXPECT_DBL(47483.0); + DFS("1 1 30"); EXPECT_DBL2(47484.0, 10959.0); + /* But Windows 1903+ uses 49 as the Y2K cutoff */ + DFS("31 12 49"); EXPECT_DBL2(54788.0, 18263.0); + DFS("1 1 50"); EXPECT_DBL(18264.0); + DFS("12 31 99"); EXPECT_DBL(36525.0); + DFS("1 1 100"); EXPECT_DBL(-657434.0); + DFS("3 am 1 2"); MKRELDATE(2,1); relative += 0.125; EXPECT_DBL(relative); DFS("1 2 3 am"); EXPECT_DBL(relative); diff --git a/dlls/oleaut32/vartype.c b/dlls/oleaut32/vartype.c index f114da4ad21..dfdb0a15c51 100644 --- a/dlls/oleaut32/vartype.c +++ b/dlls/oleaut32/vartype.c @@ -7554,12 +7554,19 @@ VARIANT_MakeDate_OK: st->wDay = v1; st->wMonth = v2; - /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may - * be retrieved from: - * HKCU\Control Panel\International\Calendars\TwoDigitYearMax - * But Wine doesn't have/use that key as at the time of writing. + /* FIXME: For 2 digit dates old versions of Windows used 29 but + * Windows 10 1903 and greater use 49. This cutoff may also be modified by + * setting the value as a string for the relevant calendar id in the + * registry. + * + * For instance to emulate old Windows versions: + * [HKCU\Control Panel\International\Calendars\TwoDigitYearMax] + * "1"="29" + * (also 2, 9, 10, 11 and 12 for the other Gregorian calendars) + * + * But Wine doesn't have/use that key at the time of writing. */ - st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3; + st->wYear = v3 <= 49 ? 2000 + v3 : v3 <= 99 ? 1900 + v3 : v3; TRACE("Returning date %d/%d/%d\n", v1, v2, st->wYear); return S_OK; }