Repository: EltonChou/EorzeaEnv

Issue:
Time rollover is handled incorrectly 
While trying to calculate some windows where the time, moon phase and weather all matched (for an S rank) I discovered that the windows returned were incomplete (when compared to other tools).

After further testing I found that the provided `weather_period` generator was returning 24, 16, and 8. When 24 is set as the bell in `EorzeaTime` it does not calculate the expected moon phase that would match the time and weather causing incorrect results. Now I am not an expert in time libraries (and do not wish to be) but 24 is an invalid hour (or bell in this case). 

The source is that the [`bell` setter allows 24](https://github.com/EltonChou/EorzeaEnv/blob/34e623e8a5d4bc188381db6a12f59608a0517ac9/EorzeaEnv/eorzea_time.py#L109) and the [`minute` setter allows 60](https://github.com/EltonChou/EorzeaEnv/blob/34e623e8a5d4bc188381db6a12f59608a0517ac9/EorzeaEnv/eorzea_time.py#L124), both should be `>=` instead of `>`. I would have submitted a PR but I was just going to make an issue to check if I was maybe missing something.

Hints from issue comments:
@EltonChou: Yes, they should be `>=`. 
This is my mistake.  
[Ref](https://github.com/Rogueadyn/SaintCoinach/blob/f969b441584688c02dde2fadac548c4a5aaa3faa/SaintCoinach/EorzeaDateTime.cs)

You can submit a PR if you want.
It would be helpful if you can add some test cases about this issue.

Solution patch:
diff --git a/EorzeaEnv/eorzea_time.py b/EorzeaEnv/eorzea_time.py
index 8b805e1..eed9608 100644
--- a/EorzeaEnv/eorzea_time.py
+++ b/EorzeaEnv/eorzea_time.py
@@ -106,7 +106,7 @@ def bell(self, value):
             self._bell += 24
             self.sun = self.sun - 1
 
-        while self._bell > 24:
+        while self._bell >= 24:
             self._bell -= 24
             self.sun = self.sun + 1
 
@@ -121,7 +121,7 @@ def minute(self, value):
             self._minute += 60
             self.bell = self.bell - 1
 
-        while self._minute > 60:
+        while self._minute >= 60:
             self._minute -= 60
             self.bell = self.bell + 1
 


Test patch:
diff --git a/test/test_time.py b/test/test_time.py
index feed546..9d7816f 100644
--- a/test/test_time.py
+++ b/test/test_time.py
@@ -60,6 +60,64 @@ def test_time_operator(self):
         assert t1 != 1
         assert not t1 == 1
 
+    def test_positive_rollover(self):
+        et = EorzeaTime()
+        et.minute = 59
+        et.bell = 23
+        et.sun = 32
+        et.moon = 12
+        et.year = 999
+
+        et.minute += 1
+
+        assert et.minute == 0
+        assert et.bell == 0
+        assert et.sun == 1
+        assert et.moon == 1
+        assert et.year == 1000
+
+        et.minute += 121
+
+        assert et.minute == 1
+        assert et.bell == 2
+
+        et.bell += 49
+
+        assert et.bell == 3
+        assert et.sun == 3
+
+    def test_negative_rollover(self):
+        et = EorzeaTime()
+        et.minute = 0
+        et.bell = 0
+        et.sun = 1
+        et.moon = 2
+        et.year = 1000
+
+        et.minute -= 1
+
+        assert et.minute == 59
+        assert et.bell == 23
+        assert et.sun == 32
+        assert et.moon == 1
+
+        et.minute -= 119
+
+        assert et.minute == 0
+        assert et.bell == 22
+
+        et.bell -= 48
+
+        assert et.minute == 0
+        assert et.bell == 22
+        assert et.sun == 30
+        assert et.moon == 1
+
+        et.moon -= 11
+
+        assert et.moon == 2
+        assert et.year == 999
+
     def test_property(self):
         ts = 12700000
         et = EorzeaTime(ts)
@@ -73,16 +131,6 @@ def test_property(self):
         assert et.moon_phase == 0.50
         assert et.moon_name == "Sixth Embral Moon"
 
-        et = EorzeaTime()
-        et.moon += 13
-        et.sun += 33
-        et.bell += 26
-        et.minute += 65
-        et.moon -= 13
-        et.sun -= 33
-        et.bell -= 26
-        et.minute -= 65
-
     def test_repr(self):
         et = EorzeaTime.now()
         assert repr(et) == f"EorzeaTime({et.get_unix_time()})"