Skip to content

Commit

Permalink
Add quarter granularity (#1048)
Browse files Browse the repository at this point in the history
* Add quarter granularity

* rebase and fix

* add more cases for quarters

Co-authored-by: Mohammed Ali Zubair <[email protected]>
Co-authored-by: Jad Chaar <[email protected]>
  • Loading branch information
3 people authored Oct 22, 2021
1 parent 4d1aa4f commit f7a3aa3
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
10 changes: 8 additions & 2 deletions arrow/arrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"day",
"week",
"month",
"quarter",
"year",
]

Expand Down Expand Up @@ -132,6 +133,7 @@ class Arrow:
_SECS_PER_DAY: Final[int] = 60 * 60 * 24
_SECS_PER_WEEK: Final[int] = 60 * 60 * 24 * 7
_SECS_PER_MONTH: Final[float] = 60 * 60 * 24 * 30.5
_SECS_PER_QUARTER: Final[float] = 60 * 60 * 24 * 30.5 * 3
_SECS_PER_YEAR: Final[int] = 60 * 60 * 24 * 365

_SECS_MAP: Final[Mapping[TimeFrameLiteral, float]] = {
Expand All @@ -141,6 +143,7 @@ class Arrow:
"day": _SECS_PER_DAY,
"week": _SECS_PER_WEEK,
"month": _SECS_PER_MONTH,
"quarter": _SECS_PER_QUARTER,
"year": _SECS_PER_YEAR,
}

Expand Down Expand Up @@ -1245,12 +1248,14 @@ def humanize(
delta = sign * delta_second / self._SECS_PER_WEEK
elif granularity == "month":
delta = sign * delta_second / self._SECS_PER_MONTH
elif granularity == "quarter":
delta = sign * delta_second / self._SECS_PER_QUARTER
elif granularity == "year":
delta = sign * delta_second / self._SECS_PER_YEAR
else:
raise ValueError(
"Invalid level of granularity. "
"Please select between 'second', 'minute', 'hour', 'day', 'week', 'month' or 'year'."
"Please select between 'second', 'minute', 'hour', 'day', 'week', 'month', 'quarter' or 'year'."
)

if trunc(abs(delta)) != 1:
Expand All @@ -1275,6 +1280,7 @@ def gather_timeframes(_delta: float, _frame: TimeFrameLiteral) -> float:
delta = float(delta_second)
frames: Tuple[TimeFrameLiteral, ...] = (
"year",
"quarter",
"month",
"week",
"day",
Expand All @@ -1288,7 +1294,7 @@ def gather_timeframes(_delta: float, _frame: TimeFrameLiteral) -> float:
if len(timeframes) < len(granularity):
raise ValueError(
"Invalid level of granularity. "
"Please select between 'second', 'minute', 'hour', 'day', 'week', 'month' or 'year'."
"Please select between 'second', 'minute', 'hour', 'day', 'week', 'month', 'quarter' or 'year'."
)

return locale.describe_multi(timeframes, only_distance=only_distance)
Expand Down
6 changes: 6 additions & 0 deletions arrow/locales.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
"weeks",
"month",
"months",
"quarter",
"quarters",
"year",
"years",
]
Expand Down Expand Up @@ -98,6 +100,8 @@ class Locale:
"weeks": "",
"month": "",
"months": "",
"quarter": "",
"quarters": "",
"year": "",
"years": "",
}
Expand Down Expand Up @@ -314,6 +318,8 @@ class EnglishLocale(Locale):
"weeks": "{0} weeks",
"month": "a month",
"months": "{0} months",
"quarter": "a quarter",
"quarters": "{0} quarters",
"year": "a year",
"years": "{0} years",
}
Expand Down
20 changes: 20 additions & 0 deletions tests/test_arrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -1935,9 +1935,29 @@ def test_granularity(self):
assert later506.humanize(self.now, granularity="week") == "in 82 weeks"
assert self.now.humanize(later506, granularity="month") == "18 months ago"
assert later506.humanize(self.now, granularity="month") == "in 18 months"
assert self.now.humanize(later506, granularity="quarter") == "6 quarters ago"
assert later506.humanize(self.now, granularity="quarter") == "in 6 quarters"
assert self.now.humanize(later506, granularity="year") == "a year ago"
assert later506.humanize(self.now, granularity="year") == "in a year"

assert self.now.humanize(later1, granularity="quarter") == "0 quarters ago"
assert later1.humanize(self.now, granularity="quarter") == "in 0 quarters"
later107 = self.now.shift(seconds=10 ** 7)
assert self.now.humanize(later107, granularity="quarter") == "a quarter ago"
assert later107.humanize(self.now, granularity="quarter") == "in a quarter"
later207 = self.now.shift(seconds=2 * 10 ** 7)
assert self.now.humanize(later207, granularity="quarter") == "2 quarters ago"
assert later207.humanize(self.now, granularity="quarter") == "in 2 quarters"
later307 = self.now.shift(seconds=3 * 10 ** 7)
assert self.now.humanize(later307, granularity="quarter") == "3 quarters ago"
assert later307.humanize(self.now, granularity="quarter") == "in 3 quarters"
later377 = self.now.shift(seconds=3.7 * 10 ** 7)
assert self.now.humanize(later377, granularity="quarter") == "4 quarters ago"
assert later377.humanize(self.now, granularity="quarter") == "in 4 quarters"
later407 = self.now.shift(seconds=4 * 10 ** 7)
assert self.now.humanize(later407, granularity="quarter") == "5 quarters ago"
assert later407.humanize(self.now, granularity="quarter") == "in 5 quarters"

later108 = self.now.shift(seconds=10 ** 8)
assert self.now.humanize(later108, granularity="year") == "3 years ago"
assert later108.humanize(self.now, granularity="year") == "in 3 years"
Expand Down

0 comments on commit f7a3aa3

Please sign in to comment.