Francois Gouget : oleaut32: Update the VarDateFromStr() Y2K cutoff.

Alexandre Julliard julliard at winehq.org
Tue Jul 20 15:11:04 CDT 2021


Module: wine
Branch: master
Commit: c83b7a0f39161aec4165d3d616c08afd18a62998
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=c83b7a0f39161aec4165d3d616c08afd18a62998

Author: Francois Gouget <fgouget at codeweavers.com>
Date:   Fri Jul 16 16:07:08 2021 +0200

oleaut32: Update the VarDateFromStr() Y2K cutoff.

Old Windows versions used 29 as the Y2K cutoff, that is they mapped
two digit years 00-29 to 2000-2029 and years 30-99 to 1930-1999.
But starting with Windows 10 1903 the cutoff is now 49 by default.
So update Wine to match the current Windows versions and adjust the
tests to work for both.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51453
Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/oleaut32/tests/vartype.c | 43 ++++++++++++++++++++++++++++---------------
 dlls/oleaut32/vartype.c       | 17 ++++++++++++-----
 2 files changed, 40 insertions(+), 20 deletions(-)

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;
 }




More information about the wine-cvs mailing list