From b9cf290b2c81c2a9f13229651b1989f0fe9d8b0f Mon Sep 17 00:00:00 2001 From: Alex Zaytsev Date: Wed, 26 Jun 2024 20:48:06 +1000 Subject: [PATCH 1/3] Fix intersection of open periods --- projects/GKCore/GDModel/GDMCustomDate.cs | 2 +- projects/GKTests/GDModel/GDMLocationRecordTests.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/projects/GKCore/GDModel/GDMCustomDate.cs b/projects/GKCore/GDModel/GDMCustomDate.cs index 088cf6919..af7cb70b2 100644 --- a/projects/GKCore/GDModel/GDMCustomDate.cs +++ b/projects/GKCore/GDModel/GDMCustomDate.cs @@ -196,7 +196,7 @@ public static GDMDatePeriod GetIntersection(GDMCustomDate range1, GDMCustomDate GDMDate smallestEnd = r1end.IsEmpty() ? r2end : (r2end.IsEmpty() ? r1end : (r1end.CompareTo(r2end) < 0) ? r1end : r2end); // no intersection - if (greatestStart.CompareTo(smallestEnd) > 0) { + if (greatestStart.CompareTo(smallestEnd) > 0 && !greatestStart.IsEmpty() && !smallestEnd.IsEmpty()) { return GDMDatePeriod.Empty; } diff --git a/projects/GKTests/GDModel/GDMLocationRecordTests.cs b/projects/GKTests/GDModel/GDMLocationRecordTests.cs index 2b1d63af8..f4836a96a 100644 --- a/projects/GKTests/GDModel/GDMLocationRecordTests.cs +++ b/projects/GKTests/GDModel/GDMLocationRecordTests.cs @@ -406,6 +406,8 @@ public void Test_DateIntersections() Assert.AreEqual("FROM 1782 TO 1834", GDMCustomDate.GetIntersection(GetRange("FROM 1782"), GetRange("TO 1834")).StringValue); Assert.AreEqual("FROM 1782 TO 1834", GDMCustomDate.GetIntersection(GetRange("TO 1834"), GetRange("FROM 1782")).StringValue); + Assert.AreEqual("FROM 1782", GDMCustomDate.GetIntersection(GetRange("FROM 1782"), GetRange("FROM 1782")).StringValue); + Assert.AreEqual("FROM 1834", GDMCustomDate.GetIntersection(GetRange("FROM 1782"), GetRange("FROM 1834")).StringValue); Assert.AreEqual("", GDMCustomDate.GetIntersection(GetRange("FROM 1858"), GetRange("TO 1834")).StringValue); // no intersects Assert.AreEqual("", GDMCustomDate.GetIntersection(GetRange("TO 1834"), GetRange("FROM 1858")).StringValue); // no intersects From e962b410200df434d07fa7bdf6e45c16512df415 Mon Sep 17 00:00:00 2001 From: Alex Zaytsev Date: Wed, 26 Jun 2024 20:49:32 +1000 Subject: [PATCH 2/3] Add more tests --- projects/GKTests/GDModel/GDMLocationRecordTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/projects/GKTests/GDModel/GDMLocationRecordTests.cs b/projects/GKTests/GDModel/GDMLocationRecordTests.cs index f4836a96a..b6e637352 100644 --- a/projects/GKTests/GDModel/GDMLocationRecordTests.cs +++ b/projects/GKTests/GDModel/GDMLocationRecordTests.cs @@ -408,6 +408,8 @@ public void Test_DateIntersections() Assert.AreEqual("FROM 1782 TO 1834", GDMCustomDate.GetIntersection(GetRange("TO 1834"), GetRange("FROM 1782")).StringValue); Assert.AreEqual("FROM 1782", GDMCustomDate.GetIntersection(GetRange("FROM 1782"), GetRange("FROM 1782")).StringValue); Assert.AreEqual("FROM 1834", GDMCustomDate.GetIntersection(GetRange("FROM 1782"), GetRange("FROM 1834")).StringValue); + Assert.AreEqual("TO 1782", GDMCustomDate.GetIntersection(GetRange("TO 1782"), GetRange("TO 1782")).StringValue); + Assert.AreEqual("TO 1782", GDMCustomDate.GetIntersection(GetRange("TO 1782"), GetRange("TO 1834")).StringValue); Assert.AreEqual("", GDMCustomDate.GetIntersection(GetRange("FROM 1858"), GetRange("TO 1834")).StringValue); // no intersects Assert.AreEqual("", GDMCustomDate.GetIntersection(GetRange("TO 1834"), GetRange("FROM 1858")).StringValue); // no intersects From a6c0e36f6dea78949d3def7a1d5676e80bb3d6bf Mon Sep 17 00:00:00 2001 From: Alex Zaytsev Date: Thu, 27 Jun 2024 11:09:01 +1000 Subject: [PATCH 3/3] Add methods to increment / decrement GDMDate --- projects/GKCore/GDModel/GDMDate.cs | 112 ++++++++++++++++++++++- projects/GKTests/GDModel/GDMDateTests.cs | 40 +++++++- 2 files changed, 150 insertions(+), 2 deletions(-) diff --git a/projects/GKCore/GDModel/GDMDate.cs b/projects/GKCore/GDModel/GDMDate.cs index 248da1f24..198c77ac7 100644 --- a/projects/GKCore/GDModel/GDMDate.cs +++ b/projects/GKCore/GDModel/GDMDate.cs @@ -135,7 +135,7 @@ public override void Clear() } /// - /// This function is intended only for checking the completeness of parts of the date + /// This function is intended only for checking the completeness of parts of the date /// (year, month and day are defined, are not unknown). /// public bool IsValidDate() @@ -588,5 +588,115 @@ public override void GetDateRange(out GDMDate dateStart, out GDMDate dateEnd) dateStart = this; dateEnd = this; } + + public static GDMDate Increment(GDMDate date) + { + if (date.IsEmpty()) { + return Empty; + } + + var calendar = date.fCalendar; + var day = date.fDay; + var month = date.fMonth; + var year = date.fYear; + var yearBc = date.fYearBC; + + Increment(ref day, ref month, ref year, ref yearBc, calendar); + + var result = new GDMDate(); + result.SetRawData(date.fApproximated, calendar, year, yearBc, date.fYearModifier, month, day); + return result; + } + + private static void Increment(ref byte day, ref byte month, ref short year, ref bool yearBC, + GDMCalendar calendar) + { + if (day > 0) { + if (day < DaysInMonth(yearBC, year, month, calendar)) { + day++; + return; + } + + day = 1; + } + + if (month > 0) { + if (month < 12) { + month++; + return; + } + + month = 1; + } + + if (year == 1 && yearBC) { + yearBC = false; + } else { + year++; + } + } + + public static GDMDate Decrement(GDMDate date) + { + if (date.IsEmpty()) { + return Empty; + } + + var calendar = date.fCalendar; + var day = date.fDay; + var month = date.fMonth; + var year = date.fYear; + var yearBc = date.fYearBC; + + Decrement(ref yearBc, ref year, ref month, ref day, calendar); + + var result = new GDMDate(); + result.SetRawData(date.fApproximated, calendar, year, yearBc, date.fYearModifier, month, day); + return result; + } + + private static void Decrement(ref bool yearBc, ref short year, ref byte month, ref byte day, + GDMCalendar calendar) + { + if (day > 1) { + day--; + return; + } + + var monthDecremented = month > 1; + if (monthDecremented) { + month--; + } else if (month > 0) { + month = 12; + } + + if (day > 0) { + day = DaysInMonth(yearBc, year, month, calendar); + } + + if (monthDecremented) return; + + if (year == 1 && !yearBc) { + yearBc = true; + } else { + year--; + } + } + + private static byte DaysInMonth(bool yearBC, short year, byte month, GDMCalendar calendar) + { + if (yearBC) { + year -= 1; + if (year == 0) { + year = 4; // DateTime.DaysInMonth does not support year 0 + } + } + + if (calendar == GDMCalendar.dcJulian && month == 2 && year % 4 == 0) { + return 29; + } + + return (byte)DateTime.DaysInMonth(year, month); + } } } diff --git a/projects/GKTests/GDModel/GDMDateTests.cs b/projects/GKTests/GDModel/GDMDateTests.cs index 8ca597937..c6d60636d 100644 --- a/projects/GKTests/GDModel/GDMDateTests.cs +++ b/projects/GKTests/GDModel/GDMDateTests.cs @@ -737,8 +737,46 @@ public void Test_CreateByFormattedStr() Assert.AreEqual("20 DEC 1980", GDMDate.CreateByFormattedStr("20/12/1980", false).StringValue); Assert.AreEqual("DEC 1980", GDMDate.CreateByFormattedStr("__/12/1980", false).StringValue); Assert.AreEqual(null, GDMDate.CreateByFormattedStr("1980", false)); - + Assert.Throws(typeof(GDMDateException), () => { GDMDate.CreateByFormattedStr("1980", true); }); } + + [Test] + [TestCase("", "")] + [TestCase("2024", "2025")] + [TestCase("001B.C.", "001")] + [TestCase("OCT 2024", "NOV 2024")] + [TestCase("DEC 2024", "JAN 2025")] + [TestCase("01 OCT 2024", "02 OCT 2024")] + [TestCase("31 OCT 2024", "01 NOV 2024")] + [TestCase("31 DEC 2024", "01 JAN 2025")] + [TestCase("28 FEB 1900", "01 MAR 1900")] + [TestCase("28 FEB 2000", "29 FEB 2000")] + [TestCase("29 FEB 2000", "01 MAR 2000")] + [TestCase("28 FEB 2023", "01 MAR 2023")] + [TestCase("28 FEB 2024", "29 FEB 2024")] + [TestCase("29 FEB 2024", "01 MAR 2024")] + [TestCase("28 FEB 001B.C.", "29 FEB 001B.C.")] + [TestCase("29 FEB 001B.C.", "01 MAR 001B.C.")] + [TestCase("28 FEB 005B.C.", "29 FEB 005B.C.")] + [TestCase("29 FEB 005B.C.", "01 MAR 005B.C.")] + [TestCase("28 FEB 097B.C.", "29 FEB 097B.C.")] + [TestCase("29 FEB 097B.C.", "01 MAR 097B.C.")] + [TestCase("28 FEB 101B.C.", "01 MAR 101B.C.")] + [TestCase("@#DJULIAN@ 29 FEB 2024", "@#DJULIAN@ 01 MAR 2024")] + [TestCase("@#DJULIAN@ 28 FEB 1900", "@#DJULIAN@ 29 FEB 1900")] + [TestCase("@#DJULIAN@ 29 FEB 1900", "@#DJULIAN@ 01 MAR 1900")] + [TestCase("@#DJULIAN@ 28 FEB 2000", "@#DJULIAN@ 29 FEB 2000")] + [TestCase("@#DJULIAN@ 29 FEB 2000", "@#DJULIAN@ 01 MAR 2000")] + [TestCase("@#DJULIAN@ 28 FEB 2023", "@#DJULIAN@ 01 MAR 2023")] + [TestCase("@#DJULIAN@ 29 FEB 2024", "@#DJULIAN@ 01 MAR 2024")] + public void Test_Increment_Decrement(string value, string expected) + { + var d = new GDMDate(); + d.StringValue = value; + Assert.AreEqual(expected, GDMDate.Increment(d).StringValue); + d.StringValue = expected; + Assert.AreEqual(value, GDMDate.Decrement(d).StringValue); + } } }