Skip to content

Commit 0e9f3c3

Browse files
perrymanmdktarbet
andauthored
Correct computation of date/times for most-used calendar intervals (#97)
* Correct computation of date/times for most-used calendar intervals * Update setup.cfg * Update pyproject.toml --------- Co-authored-by: Karl Tarbet <ktarbet@users.noreply.github.com>
1 parent 1887a34 commit 0e9f3c3

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "hec-dss-python"
3-
version = "0.1.23"
3+
version = "0.1.24"
44
description = "Python wrapper for the HEC-DSS file database C library."
55
authors = ["Hydrologic Engineering Center"]
66
license = "MIT"

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = hecdss
3-
version = 0.1.23
3+
version = 0.1.24
44
author = Hydrologic Engineering Center
55
author_email =hec.dss@usace.army.mil
66
description = Python wrapper for the HEC-DSS file database C library.

src/hecdss/regular_timeseries.py

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,55 @@ def _interval_to_times(self, new_interval):
159159
Args:
160160
new_interval (int): The new interval in seconds.
161161
"""
162+
is_leap = lambda y: y % 4 == 0 and y % 100 != 0 or y % 400 == 0
163+
last_day = lambda y, m: 31 if m in (1,3,5,7,8,10,12) else 30 if m in (4,6,9,11) else 29 if is_leap(y) else 28
162164
if type(self.start_date) == datetime:
163-
self.times = []
164-
for i in range(len(self.values)):
165-
self.times.append((self.start_date + (i * timedelta(seconds=new_interval))).replace(microsecond=0, tzinfo=ZoneInfo(self.time_zone_name) if self.time_zone_name else None))
165+
tz = ZoneInfo(self.time_zone_name) if self.time_zone_name else None
166+
first_time = self.start_date.replace(microsecond=0, tzinfo=tz)
167+
count = len(self.values)
168+
if new_interval <= 604800:
169+
# --------------------- #
170+
# non-calendar interval #
171+
# --------------------- #
172+
span = timedelta(seconds=new_interval)
173+
self.times = [(first_time + i * span) for i in range(count)]
174+
elif new_interval == 864000:
175+
# ------------------ #
176+
# Tri-Month interval #
177+
# ------------------ #
178+
raise ValueError("Tri-Month interval not currently supported")
179+
elif new_interval == 1296000:
180+
# ------------------- #
181+
# Semi-Month interval #
182+
# ------------------- #
183+
raise ValueError("Semi-Month interval not currently supported")
184+
elif new_interval == 2592000:
185+
# ---------------- #
186+
# 1-Month interval #
187+
# ---------------- #
188+
self.times = [first_time]
189+
for i in range(1, count):
190+
y, m, d, h, n, s = self.times[-1].timetuple()[:6]
191+
if m == 12:
192+
y += 1
193+
m = 1
194+
else:
195+
m += 1
196+
d = min(last_day(y, m), first_time.day)
197+
self.times.append(datetime(y, m, d, h, n, s, tzinfo=tz))
198+
elif new_interval == 31536000:
199+
# --------------- #
200+
# 1-Year interval #
201+
# --------------- #
202+
self.times = [first_time]
203+
for i in range(1, count):
204+
y, m, d, h, n, s = self.times[-1].timetuple()[:6]
205+
y += 1
206+
d = min(last_day(y, m), first_time.day)
207+
self.times.append(datetime(y, m, d, h, n, s, tzinfo=tz))
208+
else:
209+
raise ValueError(f"Invalid interval seconds: {new_interval}")
210+
166211

167212
def _generate_times(self):
168213
"""

0 commit comments

Comments
 (0)