hdx-python-utilities 3.9.2__tar.gz → 3.9.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/PKG-INFO +1 -1
  2. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/documentation/index.md +12 -0
  3. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/requirements.txt +1 -1
  4. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/_version.py +2 -2
  5. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/dateparse.py +61 -1
  6. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_dateparse.py +147 -0
  7. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/.coveragerc +0 -0
  8. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/.github/workflows/publish-test.yaml +0 -0
  9. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/.github/workflows/publish.yaml +0 -0
  10. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/.github/workflows/run-python-tests.yaml +0 -0
  11. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/.gitignore +0 -0
  12. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/.pre-commit-config.yaml +0 -0
  13. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/CONTRIBUTING.md +0 -0
  14. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/LICENSE +0 -0
  15. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/README.md +0 -0
  16. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/documentation/.readthedocs.yaml +0 -0
  17. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/documentation/mkdocs.yaml +0 -0
  18. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/hatch.toml +0 -0
  19. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/pyproject.toml +0 -0
  20. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/pytest.ini +0 -0
  21. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/ruff.toml +0 -0
  22. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/__init__.py +0 -0
  23. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/base_downloader.py +0 -0
  24. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/compare.py +0 -0
  25. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/dictandlist.py +0 -0
  26. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/downloader.py +0 -0
  27. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/easy_logging.py +0 -0
  28. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/email.py +0 -0
  29. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/encoding.py +0 -0
  30. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/error_handler.py +0 -0
  31. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/errors_onexit.py +0 -0
  32. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/frictionless_wrapper.py +0 -0
  33. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/html.py +0 -0
  34. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/loader.py +0 -0
  35. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/matching.py +0 -0
  36. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/path.py +0 -0
  37. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/retriever.py +0 -0
  38. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/saver.py +0 -0
  39. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/session.py +0 -0
  40. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/state.py +0 -0
  41. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/text.py +0 -0
  42. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/typehint.py +0 -0
  43. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/useragent.py +0 -0
  44. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/src/hdx/utilities/uuid.py +0 -0
  45. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/compare/test_csv_processing.csv +0 -0
  46. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/compare/test_csv_processing2.csv +0 -0
  47. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/empty.yaml +0 -0
  48. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/hdx_config.json +0 -0
  49. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/hdx_config.yaml +0 -0
  50. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/hdx_email_configuration.json +0 -0
  51. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/hdx_email_configuration.yaml +0 -0
  52. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/json_csv.yaml +0 -0
  53. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/logging_config.json +0 -0
  54. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/logging_config.yaml +0 -0
  55. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/project_configuration.json +0 -0
  56. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/project_configuration.yaml +0 -0
  57. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/smtp_config.json +0 -0
  58. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/smtp_config.yaml +0 -0
  59. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/user_agent_config.yaml +0 -0
  60. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/user_agent_config2.yaml +0 -0
  61. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/user_agent_config3.yaml +0 -0
  62. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/config/user_agent_config_wrong.yaml +0 -0
  63. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/basicauth.txt +0 -0
  64. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/bearertoken.txt +0 -0
  65. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/extra_params.json +0 -0
  66. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/extra_params.yaml +0 -0
  67. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/extra_params_tree.yaml +0 -0
  68. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/test_csv_processing.csv +0 -0
  69. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/test_csv_processing_blanks.csv +0 -0
  70. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/test_data.csv +0 -0
  71. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/test_data.xlsx +0 -0
  72. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/test_data1.csv/empty.txt +0 -0
  73. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/test_data2.csv +0 -0
  74. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/test_json_processing.json +0 -0
  75. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/test_xls_processing.xls +0 -0
  76. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/downloader/test_xlsx_processing.xlsx +0 -0
  77. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/html/response.html +0 -0
  78. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/loader/empty.json +0 -0
  79. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/loader/empty.yaml +0 -0
  80. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/loader/empty_list.json +0 -0
  81. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/retriever/fallbacks/test.csv +0 -0
  82. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/retriever/fallbacks/test.json +0 -0
  83. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/retriever/fallbacks/test.txt +0 -0
  84. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/retriever/fallbacks/test.yaml +0 -0
  85. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/retriever/retriever-test.csv +0 -0
  86. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/retriever/test.csv +0 -0
  87. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/retriever/test.json +0 -0
  88. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/retriever/test.txt +0 -0
  89. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/retriever/test.yaml +0 -0
  90. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/retriever/test_hxl.csv +0 -0
  91. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/out.csv +0 -0
  92. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/out.json +0 -0
  93. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/out2.csv +0 -0
  94. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/out2.json +0 -0
  95. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/out5.json +0 -0
  96. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/out6.json +0 -0
  97. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/out7.json +0 -0
  98. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/out8.csv +0 -0
  99. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/out8.json +0 -0
  100. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/pretty-false_sortkeys-false.json +0 -0
  101. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/pretty-false_sortkeys-false.yaml +0 -0
  102. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/pretty-false_sortkeys-true.json +0 -0
  103. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/pretty-false_sortkeys-true.yaml +0 -0
  104. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/pretty-true_sortkeys-false.json +0 -0
  105. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/pretty-true_sortkeys-false.yaml +0 -0
  106. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/pretty-true_sortkeys-true.json +0 -0
  107. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/saver/pretty-true_sortkeys-true.yaml +0 -0
  108. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/state/analysis_dates.txt +0 -0
  109. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/state/last_build_date.txt +0 -0
  110. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/fixtures/test_data.csv +0 -0
  111. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/conftest.py +0 -0
  112. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_compare.py +0 -0
  113. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_dictandlist.py +0 -0
  114. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_downloader.py +0 -0
  115. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_easy_logging.py +0 -0
  116. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_email.py +0 -0
  117. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_encoding.py +0 -0
  118. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_error_handler.py +0 -0
  119. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_html.py +0 -0
  120. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_loader.py +0 -0
  121. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_matching.py +0 -0
  122. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_path.py +0 -0
  123. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_retriever.py +0 -0
  124. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_saver.py +0 -0
  125. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_state.py +0 -0
  126. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_text.py +0 -0
  127. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_useragent.py +0 -0
  128. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/test_uuid.py +0 -0
  129. {hdx_python_utilities-3.9.2 → hdx_python_utilities-3.9.3}/tests/hdx/utilities/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hdx-python-utilities
3
- Version: 3.9.2
3
+ Version: 3.9.3
4
4
  Summary: HDX Python Utilities for streaming tabular data, date and time handling and other helpful functions
5
5
  Project-URL: Homepage, https://github.com/OCHA-DAP/hdx-python-utilities
6
6
  Author-email: Michael Rans <rans@email.com>
@@ -341,6 +341,18 @@ Examples:
341
341
  )
342
342
  assert date == expected_date
343
343
 
344
+ # Handle quarter
345
+ date = datetime(2020, 7, 31, 7, 33, 54, tzinfo=timezone.utc)
346
+ assert get_quarter(date) == 3
347
+ year = 2022
348
+ quarter = 3
349
+ assert get_quarter_start(year, quarter) == datetime(
350
+ 2022, 7, 1, tzinfo=timezone.utc
351
+ )
352
+ assert get_quarter_end(year, quarter) == datetime(
353
+ 2022, 9, 30, 23, 59, 59, tzinfo=timezone.utc
354
+ )
355
+
344
356
  ## Loading and saving JSON and YAML
345
357
 
346
358
  Examples:
@@ -200,7 +200,7 @@ rpds-py==0.27.1
200
200
  # referencing
201
201
  ruamel-yaml==0.18.15
202
202
  # via hdx-python-utilities (pyproject.toml)
203
- ruamel-yaml-clib==0.2.12
203
+ ruamel-yaml-clib==0.2.14
204
204
  # via ruamel-yaml
205
205
  shellingham==1.5.4
206
206
  # via typer
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '3.9.2'
32
- __version_tuple__ = version_tuple = (3, 9, 2)
31
+ __version__ = version = '3.9.3'
32
+ __version_tuple__ = version_tuple = (3, 9, 3)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -3,7 +3,7 @@
3
3
  import re
4
4
  import time
5
5
  from calendar import monthrange
6
- from datetime import datetime, timezone
6
+ from datetime import datetime, timedelta, timezone
7
7
  from io import StringIO
8
8
  from typing import Dict, Optional, Tuple
9
9
 
@@ -1129,3 +1129,63 @@ def iso_string_from_datetime(date: datetime) -> str:
1129
1129
  str: ISO formatted date without any time elements
1130
1130
  """
1131
1131
  return date.date().isoformat()
1132
+
1133
+
1134
+ def get_quarter(date: datetime) -> int:
1135
+ """Get the quarter of the given date
1136
+
1137
+ Args:
1138
+ date (datetime): Date
1139
+
1140
+ Returns:
1141
+ int: Quarter in which the given date is contained
1142
+ """
1143
+ return (date.month - 1) // 3 + 1
1144
+
1145
+
1146
+ def get_quarter_start(year: int, quarter: int) -> datetime:
1147
+ """Get the first day of the quarter in which a given date is contained
1148
+
1149
+ Args:
1150
+ year (int): Year
1151
+ quarter (int): Quarter
1152
+
1153
+ Returns:
1154
+ datetime: First day of quarter
1155
+ """
1156
+ month = 3 * (quarter - 1) + 1
1157
+ return datetime(year, month, 1, tzinfo=timezone.utc)
1158
+
1159
+
1160
+ def get_quarter_end(
1161
+ year: int, quarter: int, max_time: bool = True, include_microseconds: bool = False
1162
+ ):
1163
+ """Get the last day of the quarter in which a given date is contained
1164
+
1165
+ Args:
1166
+ year (int): Year
1167
+ quarter (int): Quarter
1168
+ max_time (bool): Make date time component 23:59:59:999999. Defaults to True.
1169
+ include_microseconds (bool): Includes microseconds if True. Defaults to False.
1170
+
1171
+ Returns:
1172
+ datetime: First day of quarter
1173
+ """
1174
+ year = year + 3 * quarter // 12
1175
+ month = 3 * quarter % 12 + 1
1176
+ if max_time:
1177
+ hours = 23
1178
+ minutes = 59
1179
+ seconds = 59
1180
+ if include_microseconds:
1181
+ microseconds = 999999
1182
+ else:
1183
+ microseconds = 0
1184
+ else:
1185
+ hours = 0
1186
+ minutes = 0
1187
+ seconds = 0
1188
+ microseconds = 0
1189
+ return datetime(
1190
+ year, month, 1, hours, minutes, seconds, microseconds, tzinfo=timezone.utc
1191
+ ) + timedelta(days=-1)
@@ -7,6 +7,9 @@ from dateutil.parser import ParserError
7
7
 
8
8
  from hdx.utilities.dateparse import (
9
9
  get_datetime_from_timestamp,
10
+ get_quarter,
11
+ get_quarter_end,
12
+ get_quarter_start,
10
13
  get_timestamp_from_datetime,
11
14
  iso_string_from_datetime,
12
15
  now_utc,
@@ -301,3 +304,147 @@ class TestDateParse:
301
304
  date = datetime(2020, 7, 31, 7, 33, 54, tzinfo=timezone.utc)
302
305
  string = iso_string_from_datetime(date)
303
306
  assert string == "2020-07-31"
307
+
308
+ def test_get_quarter(self):
309
+ date = datetime(2020, 7, 31, 7, 33, 54, tzinfo=timezone.utc)
310
+ assert get_quarter(date) == 3
311
+ assert (
312
+ get_quarter(datetime(year=2021, month=10, day=5, tzinfo=timezone.utc)) == 4
313
+ )
314
+ assert (
315
+ get_quarter(datetime(year=2020, month=9, day=25, tzinfo=timezone.utc)) == 3
316
+ )
317
+ assert (
318
+ get_quarter(datetime(year=2020, month=12, day=11, tzinfo=timezone.utc)) == 4
319
+ )
320
+ assert (
321
+ get_quarter(datetime(year=2020, month=1, day=2, tzinfo=timezone.utc)) == 1
322
+ )
323
+
324
+ def test_get_quarter_start_end(self):
325
+ year = 2022
326
+ quarter = 3
327
+ assert get_quarter_start(year, quarter) == datetime(
328
+ 2022, 7, 1, tzinfo=timezone.utc
329
+ )
330
+ assert get_quarter_end(year, quarter) == datetime(
331
+ 2022, 9, 30, 23, 59, 59, tzinfo=timezone.utc
332
+ )
333
+ assert get_quarter_end(year, quarter, max_time=False) == datetime(
334
+ 2022, 9, 30, tzinfo=timezone.utc
335
+ )
336
+ assert get_quarter_end(year, quarter, include_microseconds=True) == datetime(
337
+ 2022, 9, 30, 23, 59, 59, 999999, tzinfo=timezone.utc
338
+ )
339
+
340
+ date = datetime(2020, 10, 5, tzinfo=timezone.utc)
341
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
342
+ 2020, 10, 1, tzinfo=timezone.utc
343
+ )
344
+ assert get_quarter_end(
345
+ date.year, get_quarter(date), max_time=False
346
+ ) == datetime(2020, 12, 31, tzinfo=timezone.utc)
347
+
348
+ date = datetime(2020, 9, 25, tzinfo=timezone.utc)
349
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
350
+ 2020, 7, 1, tzinfo=timezone.utc
351
+ )
352
+ assert get_quarter_end(
353
+ date.year, get_quarter(date), max_time=False
354
+ ) == datetime(2020, 9, 30, tzinfo=timezone.utc)
355
+
356
+ date = datetime(2020, 7, 1, tzinfo=timezone.utc)
357
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
358
+ 2020, 7, 1, tzinfo=timezone.utc
359
+ )
360
+ assert get_quarter_end(
361
+ date.year, get_quarter(date), max_time=False
362
+ ) == datetime(2020, 9, 30, tzinfo=timezone.utc)
363
+
364
+ date = datetime(2020, 9, 30, tzinfo=timezone.utc)
365
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
366
+ 2020, 7, 1, tzinfo=timezone.utc
367
+ )
368
+ assert get_quarter_end(
369
+ date.year, get_quarter(date), max_time=False
370
+ ) == datetime(2020, 9, 30, tzinfo=timezone.utc)
371
+
372
+ date = datetime(2020, 12, 11, tzinfo=timezone.utc)
373
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
374
+ 2020, 10, 1, tzinfo=timezone.utc
375
+ )
376
+ assert get_quarter_end(
377
+ date.year, get_quarter(date), max_time=False
378
+ ) == datetime(2020, 12, 31, tzinfo=timezone.utc)
379
+
380
+ date = datetime(2020, 10, 1, tzinfo=timezone.utc)
381
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
382
+ 2020, 10, 1, tzinfo=timezone.utc
383
+ )
384
+ assert get_quarter_end(
385
+ date.year, get_quarter(date), max_time=False
386
+ ) == datetime(2020, 12, 31, tzinfo=timezone.utc)
387
+
388
+ date = datetime(2020, 12, 31, tzinfo=timezone.utc)
389
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
390
+ 2020, 10, 1, tzinfo=timezone.utc
391
+ )
392
+ assert get_quarter_end(
393
+ date.year, get_quarter(date), max_time=False
394
+ ) == datetime(2020, 12, 31, tzinfo=timezone.utc)
395
+
396
+ date = datetime(2020, 1, 2, tzinfo=timezone.utc)
397
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
398
+ 2020, 1, 1, tzinfo=timezone.utc
399
+ )
400
+ assert get_quarter_end(
401
+ date.year, get_quarter(date), max_time=False
402
+ ) == datetime(2020, 3, 31, tzinfo=timezone.utc)
403
+
404
+ date = datetime(2020, 1, 1, tzinfo=timezone.utc)
405
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
406
+ 2020, 1, 1, tzinfo=timezone.utc
407
+ )
408
+ assert get_quarter_end(
409
+ date.year, get_quarter(date), max_time=False
410
+ ) == datetime(2020, 3, 31, tzinfo=timezone.utc)
411
+
412
+ date = datetime(2020, 3, 31, tzinfo=timezone.utc)
413
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
414
+ 2020, 1, 1, tzinfo=timezone.utc
415
+ )
416
+ assert get_quarter_end(
417
+ date.year, get_quarter(date), max_time=False
418
+ ) == datetime(2020, 3, 31, tzinfo=timezone.utc)
419
+
420
+ date = datetime(2020, 2, 29, tzinfo=timezone.utc)
421
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
422
+ 2020, 1, 1, tzinfo=timezone.utc
423
+ )
424
+ assert get_quarter_end(
425
+ date.year, get_quarter(date), max_time=False
426
+ ) == datetime(2020, 3, 31, tzinfo=timezone.utc)
427
+
428
+ date = datetime(2020, 5, 6, tzinfo=timezone.utc)
429
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
430
+ 2020, 4, 1, tzinfo=timezone.utc
431
+ )
432
+ assert get_quarter_end(
433
+ date.year, get_quarter(date), max_time=False
434
+ ) == datetime(2020, 6, 30, tzinfo=timezone.utc)
435
+
436
+ date = datetime(2020, 4, 1, tzinfo=timezone.utc)
437
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
438
+ 2020, 4, 1, tzinfo=timezone.utc
439
+ )
440
+ assert get_quarter_end(
441
+ date.year, get_quarter(date), max_time=False
442
+ ) == datetime(2020, 6, 30, tzinfo=timezone.utc)
443
+
444
+ date = datetime(2020, 6, 30, tzinfo=timezone.utc)
445
+ assert get_quarter_start(date.year, get_quarter(date)) == datetime(
446
+ 2020, 4, 1, tzinfo=timezone.utc
447
+ )
448
+ assert get_quarter_end(
449
+ date.year, get_quarter(date), max_time=False
450
+ ) == datetime(2020, 6, 30, tzinfo=timezone.utc)