|
67 | 67 | "import random\n",
|
68 | 68 | "from datetime import timedelta\n",
|
69 | 69 | "from datetime import datetime\n",
|
| 70 | + "from datetime import timezone\n", |
70 | 71 | "import calendar"
|
71 | 72 | ]
|
72 | 73 | },
|
|
102 | 103 | " if time_arg is None:\n",
|
103 | 104 | " return uuid.uuid1(node, clock_seq)\n",
|
104 | 105 | " if hasattr(time_arg, 'utctimetuple'):\n",
|
| 106 | + " # this is different from the Cassandra version, we assume that a naive datetime is in system time and convert it to UTC\n", |
| 107 | + " # we do this because naive datetimes are interpreted as timestamps (without timezone) in postgres\n", |
| 108 | + " if time_arg.tzinfo is None:\n", |
| 109 | + " time_arg = time_arg.astimezone(timezone.utc)\n", |
105 | 110 | " seconds = int(calendar.timegm(time_arg.utctimetuple()))\n",
|
106 | 111 | " microseconds = (seconds * 1e6) + time_arg.time().microsecond\n",
|
107 | 112 | " else:\n",
|
|
291 | 296 | "source": [
|
292 | 297 | "#| export\n",
|
293 | 298 | "class UUIDTimeRange:\n",
|
294 |
| - " def __init__(self, start_date: Optional[datetime] = None, end_date: Optional[datetime] = None, start_inclusive=True, end_inclusive=False):\n", |
| 299 | + " def __init__(self, start_date: Optional[datetime] = None, end_date: Optional[datetime] = None, time_delta: Optional[timedelta] = None, start_inclusive=True, end_inclusive=False):\n", |
295 | 300 | " \"\"\"\n",
|
296 |
| - " A UUIDTimeRange is a time range predicate on the UUID Version 1 timestamps.\n", |
| 301 | + " A UUIDTimeRange is a time range predicate on the UUID Version 1 timestamps. \n", |
| 302 | + " \n", |
| 303 | + " Note that naive datetime objects are interpreted as local time on the python client side and converted to UTC before being sent to the database.\n", |
297 | 304 | " \"\"\"\n",
|
298 | 305 | " if start_date is not None and end_date is not None:\n",
|
299 | 306 | " if start_date > end_date:\n",
|
300 | 307 | " raise Exception(\"start_date must be before end_date\")\n",
|
301 | 308 | " \n",
|
302 | 309 | " if start_date is None and end_date is None:\n",
|
303 | 310 | " raise Exception(\"start_date and end_date cannot both be None\")\n",
|
| 311 | + " \n", |
| 312 | + " if start_date is not None and start_date.tzinfo is None:\n", |
| 313 | + " start_date = start_date.astimezone(timezone.utc)\n", |
| 314 | + "\n", |
| 315 | + " if end_date is not None and end_date.tzinfo is None:\n", |
| 316 | + " end_date = end_date.astimezone(timezone.utc)\n", |
| 317 | + " \n", |
| 318 | + " if time_delta is not None:\n", |
| 319 | + " if end_date is None:\n", |
| 320 | + " end_date = start_date + time_delta\n", |
| 321 | + " elif start_date is None:\n", |
| 322 | + " start_date = end_date - time_delta\n", |
| 323 | + " else:\n", |
| 324 | + " raise Exception(\"time_delta, start_date and end_date cannot all be specified at the same time\")\n", |
304 | 325 | "\n",
|
305 | 326 | " self.start_date = start_date\n",
|
306 | 327 | " self.end_date = end_date\n",
|
307 | 328 | " self.start_inclusive = start_inclusive\n",
|
308 | 329 | " self.end_inclusive = end_inclusive\n",
|
| 330 | + " \n", |
| 331 | + " def __str__(self):\n", |
| 332 | + " start_str = f\"[{self.start_date}\" if self.start_inclusive else f\"({self.start_date}\"\n", |
| 333 | + " end_str = f\"{self.end_date}]\" if self.end_inclusive else f\"{self.end_date})\"\n", |
| 334 | + " \n", |
| 335 | + " return f\"UUIDTimeRange {start_str}, {end_str}\"\n", |
309 | 336 | "\n",
|
310 | 337 | " def build_query(self, params: List) -> Tuple[str, List]:\n",
|
311 | 338 | " column = \"uuid_timestamp(id)\"\n",
|
|
1135 | 1162 | "execution_count": null,
|
1136 | 1163 | "metadata": {},
|
1137 | 1164 | "outputs": [
|
| 1165 | + { |
| 1166 | + "name": "stderr", |
| 1167 | + "output_type": "stream", |
| 1168 | + "text": [ |
| 1169 | + "/Users/cevian/.pyenv/versions/3.11.4/envs/nbdev_env/lib/python3.11/site-packages/fastcore/docscrape.py:225: UserWarning: potentially wrong underline length... \n", |
| 1170 | + "Returns \n", |
| 1171 | + "-------- in \n", |
| 1172 | + "Retrieves similar records using a similarity query.\n", |
| 1173 | + "...\n", |
| 1174 | + " else: warn(msg)\n" |
| 1175 | + ] |
| 1176 | + }, |
1138 | 1177 | {
|
1139 | 1178 | "data": {
|
1140 | 1179 | "text/markdown": [
|
|
1409 | 1448 | "assert len(rec) == 0\n",
|
1410 | 1449 | "rec = await vec.search([1.0, 2.0], limit=4, uuid_time_filter=UUIDTimeRange(specific_datetime-timedelta(days=7)))\n",
|
1411 | 1450 | "assert len(rec) == 2\n",
|
| 1451 | + "rec = await vec.search([1.0, 2.0], limit=4, uuid_time_filter=UUIDTimeRange(start_date=specific_datetime, time_delta=timedelta(days=7)))\n", |
| 1452 | + "assert len(rec) == 1\n", |
| 1453 | + "#end is exclusive\n", |
| 1454 | + "rec = await vec.search([1.0, 2.0], limit=4, uuid_time_filter=UUIDTimeRange(end_date=specific_datetime, time_delta=timedelta(days=7)))\n", |
| 1455 | + "assert len(rec) == 0\n", |
| 1456 | + "rec = await vec.search([1.0, 2.0], limit=4, uuid_time_filter=UUIDTimeRange(end_date=specific_datetime+timedelta(seconds=1), time_delta=timedelta(days=7)))\n", |
| 1457 | + "assert len(rec) == 1\n", |
1412 | 1458 | "await vec.drop_table()\n",
|
1413 | 1459 | "await vec.close()"
|
1414 | 1460 | ]
|
|
2105 | 2151 | "assert len(rec) == 0\n",
|
2106 | 2152 | "rec = vec.search([1.0, 2.0], limit=4, uuid_time_filter=UUIDTimeRange(specific_datetime-timedelta(days=7)))\n",
|
2107 | 2153 | "assert len(rec) == 2\n",
|
| 2154 | + "rec = vec.search([1.0, 2.0], limit=4, uuid_time_filter=UUIDTimeRange(start_date=specific_datetime, time_delta=timedelta(days=7)))\n", |
| 2155 | + "assert len(rec) == 1\n", |
| 2156 | + "#end is exclusive\n", |
| 2157 | + "rec = vec.search([1.0, 2.0], limit=4, uuid_time_filter=UUIDTimeRange(end_date=specific_datetime, time_delta=timedelta(days=7)))\n", |
| 2158 | + "assert len(rec) == 0\n", |
| 2159 | + "rec = vec.search([1.0, 2.0], limit=4, uuid_time_filter=UUIDTimeRange(end_date=specific_datetime+timedelta(seconds=1), time_delta=timedelta(days=7)))\n", |
| 2160 | + "assert len(rec) == 1\n", |
2108 | 2161 | "vec.drop_table()\n",
|
2109 | 2162 | "vec.close()"
|
2110 | 2163 | ]
|
|
0 commit comments