summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release-notes.md7
-rw-r--r--src/StardewModdingAPI.Tests/Utilities/SDateTests.cs4
-rw-r--r--src/StardewModdingAPI/Utilities/SDate.cs58
3 files changed, 28 insertions, 41 deletions
diff --git a/release-notes.md b/release-notes.md
index 430bd9c8..e5721fd9 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -28,11 +28,14 @@ For power users:
## 1.15.4
For players:
-* Internal fixes to support Entoarox Framework and the upcoming SMAPI 2.0 release.
+* Fixed issues with maps loaded through Entoarox Framework.
+
+For modders:
+* Fixed edge cases in `SDate.AddDays(…)` calculations.
## 1.15.3
For players:
-* Fixed mods being marked as duplicate incorrectly in some cases.
+* Fixed mods being wrongly marked as duplicate in some cases.
## 1.15.2
For players:
diff --git a/src/StardewModdingAPI.Tests/Utilities/SDateTests.cs b/src/StardewModdingAPI.Tests/Utilities/SDateTests.cs
index 714756e0..25acbaf3 100644
--- a/src/StardewModdingAPI.Tests/Utilities/SDateTests.cs
+++ b/src/StardewModdingAPI.Tests/Utilities/SDateTests.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
@@ -104,6 +104,8 @@ namespace StardewModdingAPI.Tests.Utilities
[TestCase("15 summer Y1", -28, ExpectedResult = "15 spring Y1")] // negative season transition
[TestCase("15 summer Y2", -28 * 4, ExpectedResult = "15 summer Y1")] // negative year transition
[TestCase("01 spring Y3", -(28 * 7 + 17), ExpectedResult = "12 spring Y1")] // negative year transition
+ [TestCase("06 fall Y2", 50, ExpectedResult = "28 winter Y3")] // test for zero-index errors
+ [TestCase("06 fall Y2", 51, ExpectedResult = "01 spring Y3")] // test for zero-index errors
public string AddDays(string dateStr, int addDays)
{
return this.GetDate(dateStr).AddDays(addDays).ToString();
diff --git a/src/StardewModdingAPI/Utilities/SDate.cs b/src/StardewModdingAPI/Utilities/SDate.cs
index d7631598..5073259d 100644
--- a/src/StardewModdingAPI/Utilities/SDate.cs
+++ b/src/StardewModdingAPI/Utilities/SDate.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Linq;
using StardewValley;
@@ -86,34 +86,27 @@ namespace StardewModdingAPI.Utilities
/// <exception cref="ArithmeticException">The offset would result in an invalid date (like year 0).</exception>
public SDate AddDays(int offset)
{
- // simple case
- int day = this.Day + offset;
- string season = this.Season;
- int year = this.Year;
+ // get new hash code
+ int hashCode = this.GetHashCode() + offset;
+ if (hashCode < 1)
+ throw new ArithmeticException($"Adding {offset} days to {this} would result in a date before 01 spring Y1.");
- // handle season transition
- if (day > this.DaysInSeason || day < 1)
- {
- // get season index
- int curSeasonIndex = this.GetSeasonIndex();
-
- // get season offset
- int seasonOffset = day / this.DaysInSeason;
- if (day < 1)
- seasonOffset -= 1;
-
- // get new date
- day = this.GetWrappedIndex(day, this.DaysInSeason);
- season = this.Seasons[this.GetWrappedIndex(curSeasonIndex + seasonOffset, this.Seasons.Length)];
- year += seasonOffset / this.Seasons.Length;
- }
+ // get day
+ int day = hashCode % 28;
+ if (day == 0)
+ day = 28;
- // validate
- if (year < 1)
- throw new ArithmeticException($"Adding {offset} days to {this} would result in invalid date {day:00} {season} {year}.");
+ // get season index
+ int seasonIndex = hashCode / 28;
+ if (seasonIndex > 0 && hashCode % 28 == 0)
+ seasonIndex -= 1;
+ seasonIndex %= 4;
- // return new date
- return new SDate(day, season, year);
+ // get year
+ int year = hashCode / (this.Seasons.Length * this.DaysInSeason) + 1;
+
+ // create date
+ return new SDate(day, this.Seasons[seasonIndex], year);
}
/// <summary>Get a string representation of the date. This is mainly intended for debugging or console messages.</summary>
@@ -142,7 +135,7 @@ namespace StardewModdingAPI.Utilities
/// <summary>Get a hash code which uniquely identifies a date.</summary>
public override int GetHashCode()
{
- // return the number of days since 01 spring Y1
+ // return the number of days since 01 spring Y1 (inclusively)
int yearIndex = this.Year - 1;
return
yearIndex * this.DaysInSeason * this.SeasonsInYear
@@ -239,16 +232,5 @@ namespace StardewModdingAPI.Utilities
throw new InvalidOperationException($"The current season '{this.Season}' wasn't recognised.");
return index;
}
-
- /// <summary>Get the real index in an array which should be treated as a two-way loop.</summary>
- /// <param name="index">The index in the looped array.</param>
- /// <param name="length">The number of elements in the array.</param>
- private int GetWrappedIndex(int index, int length)
- {
- int wrapped = index % length;
- if (wrapped < 0)
- wrapped += length;
- return wrapped;
- }
}
}