Skip to content

Commit

Permalink
Date processes (#275)
Browse files Browse the repository at this point in the history
* update openeo-processes

* bump 2023.9.1

* bump 2023.9.0

* add datetime processes

* pre-commit hook
  • Loading branch information
ValentinaHutter authored Sep 11, 2024
1 parent 1c52aa9 commit ac070ca
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 0 deletions.
126 changes: 126 additions & 0 deletions openeo_processes_dask/process_implementations/dates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
from typing import Optional

import numpy as np

__all__ = [
"date_between",
"date_difference",
"date_shift",
]


def datetime_from_str(date: str):
daytime = np.datetime64(date)
return daytime


def date_between(
x: str, min: str, max: str, exclude_max: bool = False
) -> Optional[bool]:
x = datetime_from_str(x)
min = datetime_from_str(min)
max = datetime_from_str(max)
if exclude_max:
return bool((x >= min) and (x < max))
else:
return bool((x >= min) and (x <= max))


def date_difference(date1: str, date2: str, unit: Optional[str] = "second") -> float:
date1 = datetime_from_str(date1)
date2 = datetime_from_str(date2)
units = {
"millisecond": 1,
"second": 1000,
"minute": 1000 * 60,
"hour": 1000 * 60 * 60,
"day": 1000 * 60 * 60 * 24,
"week": 1000 * 60 * 60 * 24 * 7,
"month": "M",
"year": "Y",
}
if unit in units:
unit = units[unit]
if unit in ["M", "Y"]:
return float(
(
date2.astype(f"datetime64[{unit}]")
- date1.astype(f"datetime64[{unit}]")
).astype(float)
)
else:
# we do this, so the examples are fulfilled:
# date_difference(date1 = "2020-01-01T00:00:00.0Z", date2 = "2020-01-01T00:00:15.5Z") -> 15.5
return (
float(
(
date2.astype(f"datetime64[ms]") - date1.astype(f"datetime64[ms]")
).astype(float)
)
/ unit
)


def date_shift(date: str, value: int, unit: str) -> str:
if date.endswith("Z"):
end = "Z"
elif "+" in date:
end = "+" + date.split("+")[-1]
date = date.split("+")[0]
else:
end = ""
units = {
"millisecond": "ms",
"second": "s",
"minute": "m",
"hour": "h",
"day": "D",
"week": "W",
"month": "M",
"year": "Y",
}
if unit in units:
unit = units[unit]
if unit in ["M", "Y"]:
if len(date) > 7:
date_M = np.datetime64(date, "M")
day = (
int(
(np.datetime64(date, "D") - date_M.astype("datetime64[D]")).astype(
int
)
)
+ 1
)
if " " in date:
time = "T" + date.split(" ")[-1]
elif "T" in date:
time = "T" + date.split("T")[-1]
else:
time = ""
new_date = str(date_M + np.timedelta64(value, unit))
if day in [29, 30, 31]:
for i in range(3):
try:
new_daytime = f"{new_date}-{day-i}"
new_daytime_numpy = np.datetime64(new_daytime)
result = f"{new_daytime}{time}"
return result
except:
pass
elif int(day) < 10:
new_daytime = f"{new_date}-0{day}{time}"
else:
new_daytime = f"{new_date}-{day}T{time}"
new_daytime_numpy = np.datetime64(new_daytime)
return new_daytime

date = datetime_from_str(date)
return str(date_M + np.timedelta64(value, unit))

date = datetime_from_str(date)
if unit in ["ms"]:
result = str((date + np.timedelta64(value, unit)).astype(f"datetime64[{unit}]"))
else:
result = str((date + np.timedelta64(value, unit)).astype(date.dtype))
return result + end
50 changes: 50 additions & 0 deletions tests/test_dates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from openeo_processes_dask.process_implementations.dates import (
date_between,
date_difference,
date_shift,
)


def test_date_between():
assert not date_between(x="2020-01-01", min="2021-01-01", max="2022-01-01")


def test_date_difference():
assert (
date_difference(date1="2020-01-01T00:00:00.0Z", date2="2020-01-01T00:00:15.5Z")
== 15.5
)
assert (
date_difference(date1="2020-01-01T00:00:00Z", date2="2020-01-01T01:00:00+01:00")
== 0
)
assert date_difference(date1="2020-01-02", date2="2020-01-01") == -86400
assert date_difference(date1="2020-01-02", date2="2020-01-01", unit="day") == -1


def test_date_shift():
month_shift = date_shift(date="2020-02-01T17:22:45Z", value=6, unit="month")
assert month_shift == "2020-08-01T17:22:45Z"

day_shift = date_shift(date="2021-03-31T00:00:00+02:00", value=-7, unit="day")
assert day_shift == "2021-03-24T00:00:00+02:00"

year_shift = date_shift(date="2020-02-29T17:22:45Z", value=1, unit="year")
assert year_shift == "2021-02-28T17:22:45Z"

month_shift = date_shift(date="2020-01-31", value=1, unit="month")
assert month_shift == "2020-02-29"

second_shift = date_shift(date="2016-12-31T23:59:59Z", value=1, unit="second")
assert second_shift == "2017-01-01T00:00:00Z"

millisecond_shift = date_shift(
date="2018-12-31T17:22:45Z", value=1150, unit="millisecond"
)
assert millisecond_shift == "2018-12-31T17:22:46.150Z"

hour_shift = date_shift(date="2018-01-01", value=25, unit="hour")
assert hour_shift == "2018-01-02"

hour_shift = date_shift(date="2018-01-01", value=-1, unit="hour")
assert hour_shift == "2017-12-31"

0 comments on commit ac070ca

Please sign in to comment.