diff --git a/pyproject.toml b/pyproject.toml index ecf2965..6127c2a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ requires = ['appdirs', 'bleach', 'bleach_allowlist', 'httpx', 'humanize', 'quart-trio-twice', 'rethinkdb >=2.4.8'] description-file = 'README.md' classifiers = [ - 'Development Status :: 2 - Pre-Alpha', + 'Development Status :: 3 - Alpha', 'Environment :: Web Environment', 'Framework :: Trio', 'Intended Audience :: Education', diff --git a/src/acanban/__init__.py b/src/acanban/__init__.py index 02038da..0bea2fe 100644 --- a/src/acanban/__init__.py +++ b/src/acanban/__init__.py @@ -19,8 +19,9 @@ from __future__ import annotations from contextlib import asynccontextmanager -from datetime import datetime, timezone +from datetime import datetime, timedelta, timezone as tz from secrets import token_urlsafe +from time import timezone from typing import Any, AsyncIterator from urllib.parse import urlsplit @@ -45,12 +46,10 @@ __all__ = ['app'] __doc__ = 'Academic Kanban' -__version__ = '0.0.7' +__version__ = '0.1.0' - -def utc(dt: datetime) -> datetime: - """Convert the datetime object to UTC with microsecond being 0.""" - return dt.astimezone(timezone.utc).replace(microsecond=0, tzinfo=None) +# Nope, the negative operator is not a typo, see also tzset(3posix). +TZ = tz(timedelta(seconds=-timezone)) class Acanban(QuartTrio): @@ -99,8 +98,10 @@ def as_markdown(text: str) -> str: @app.template_filter('naturaltime') def fuzzytime(dt: datetime) -> str: """Convert datetime into fuzzy time in HTML with precise hovertext.""" - udt = utc(dt) - return f"{naturaltime(udt)}" + rounded = dt.replace(microsecond=0) + fuzzy = naturaltime(rounded.replace(tzinfo=None), when=datetime.utcnow()) + exact = rounded.astimezone(TZ) + return f"{fuzzy}" @app.before_serving diff --git a/tests/assets/rethinkdump/test/projects.json b/tests/assets/rethinkdump/test/projects.json index 15845d1..3d068f9 100644 --- a/tests/assets/rethinkdump/test/projects.json +++ b/tests/assets/rethinkdump/test/projects.json @@ -3,12 +3,12 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1604163600, - "timezone": "+07:00" + "timezone": "+00:00" }, "deadline": { "$reql_type$": "TIME", "epoch_time": 1611075600, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Consectetur neque ut adipisci labore. Dolor velit porro adipisci. Consectetur sed ipsum neque porro etincidunt dolor ut. Ipsum voluptatem dolorem dolorem etincidunt. Etincidunt ut dolore velit numquam quisquam. Consectetur non non non quiquia consectetur velit velit. Velit neque ipsum aliquam ut adipisci sit. Tempora voluptatem aliquam non dolore eius quaerat.", "id": "7fee498b-98ac-4173-b600-e94618f9ea1f", @@ -35,13 +35,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1607878800, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "jamesm", "deadline": { "$reql_type$": "TIME", "epoch_time": 1608742800, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Consectetur neque consectetur dolorem dolor consectetur. Labore adipisci porro labore. Eius modi labore quaerat magnam quaerat non non. Tempora adipisci aliquam ipsum dolorem modi dolor adipisci. Consectetur sed adipisci dolorem labore. Voluptatem sed magnam etincidunt modi etincidunt sit quisquam.", "name": "Velit neque porro est.", @@ -53,13 +53,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1606150800, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "evelynd", "deadline": { "$reql_type$": "TIME", "epoch_time": 1607014800, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Quaerat tempora eius etincidunt sit quaerat labore. Sit neque dolor quiquia etincidunt est tempora aliquam. Magnam amet est velit magnam dolor. Voluptatem aliquam etincidunt aliquam sit neque. Porro aliquam sed adipisci neque porro.", "name": "Etincidunt velit voluptatem voluptatem dolore.", @@ -71,13 +71,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1605978000, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "jamesm", "deadline": { "$reql_type$": "TIME", "epoch_time": 1606842000, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Aliquam dolor dolor eius. Ipsum eius est voluptatem est. Tempora est ipsum dolorem consectetur voluptatem tempora. Dolor labore ipsum porro etincidunt. Consectetur etincidunt neque tempora ipsum labore non. Consectetur labore labore neque adipisci modi numquam eius. Aliquam quaerat numquam voluptatem dolorem numquam est labore.", "name": "Dolore etincidunt neque labore sit.", @@ -88,7 +88,7 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1607239442, - "timezone": "+07:00" + "timezone": "+00:00" }, "replies": [ { @@ -97,7 +97,7 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1608385730, - "timezone": "+07:00" + "timezone": "+00:00" }, "replies": [ { @@ -106,7 +106,7 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1608974521, - "timezone": "+07:00" + "timezone": "+00:00" }, "replies": [] } @@ -118,7 +118,7 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1609023842, - "timezone": "+07:00" + "timezone": "+00:00" }, "replies": [ { @@ -127,7 +127,7 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1609242444, - "timezone": "+07:00" + "timezone": "+00:00" }, "replies": [] } @@ -141,7 +141,7 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1609284722, - "timezone": "+07:00" + "timezone": "+00:00" }, "replies": [ { @@ -150,7 +150,7 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1609338472, - "timezone": "+07:00" + "timezone": "+00:00" }, "replies": [] }, @@ -160,7 +160,7 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1609428472, - "timezone": "+07:00" + "timezone": "+00:00" }, "replies": [] } @@ -174,13 +174,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1607533200, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "opheliad", "deadline": { "$reql_type$": "TIME", "epoch_time": 1608397200, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Dolorem dolore dolore etincidunt. Amet aliquam magnam quiquia est velit porro. Sed eius eius sed ipsum. Voluptatem sit quisquam quaerat etincidunt etincidunt sit. Velit neque neque velit. Ipsum modi ut dolore velit.", "name": "Est magnam dolore magnam dolorem magnam.", @@ -192,13 +192,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1606323600, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "evelynd", "deadline": { "$reql_type$": "TIME", "epoch_time": 1607187600, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Ipsum quaerat tempora dolorem modi velit etincidunt velit. Adipisci etincidunt quisquam quisquam. Neque dolorem amet aliquam numquam. Tempora sit sed aliquam ipsum dolor modi modi. Dolor dolor sed adipisci ipsum. Voluptatem neque amet quaerat ut. Numquam dolore eius eius velit magnam.", "name": "Labore magnam porro magnam voluptatem consectetur magnam.", @@ -211,12 +211,12 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1602694800, - "timezone": "+07:00" + "timezone": "+00:00" }, "deadline": { "$reql_type$": "TIME", "epoch_time": 1611075600, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Quaerat quaerat dolor labore. Quisquam voluptatem tempora quiquia ut. Dolore quisquam tempora adipisci. Magnam eius sit neque quiquia est ipsum. Consectetur quiquia sit eius adipisci est. Adipisci tempora aliquam voluptatem etincidunt dolorem dolor. Ut ipsum quiquia etincidunt neque adipisci porro consectetur.", "id": "be7a04b8-650f-41dc-912b-10d225baff29", @@ -247,13 +247,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1607533200, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "milesc", "deadline": { "$reql_type$": "TIME", "epoch_time": 1608397200, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "# Roadmap\n Blah blah blah\n\nWe should do these things:\n\n1. First thing\n2. Second thing\n3. Last thing\n\n#Workflow\n\n- Plan\n- Implement\n- Test", "name": "Start with the project", @@ -265,13 +265,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1605546000, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "milesc", "deadline": { "$reql_type$": "TIME", "epoch_time": 1606410000, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Ipsum quaerat adipisci aliquam dolore neque voluptatem. Sed porro non non aliquam adipisci sit sit. Etincidunt neque quisquam quaerat eius. Consectetur porro sit consectetur. Non tempora voluptatem labore. Est dolorem eius non etincidunt quiquia amet porro. Quaerat ipsum quisquam numquam dolor aliquam. Voluptatem velit ipsum sit non ipsum.", "name": "Consectetur sed sed tempora modi.", @@ -283,13 +283,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1605114000, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "milesc", "deadline": { "$reql_type$": "TIME", "epoch_time": 1605978000, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Quiquia voluptatem adipisci velit quiquia quisquam adipisci ut. Est quisquam numquam quisquam magnam dolore amet. Quiquia voluptatem porro sit numquam magnam. Non velit aliquam quiquia modi non sit. Est labore velit neque etincidunt est etincidunt. Dolore quaerat sed dolorem quiquia magnam dolorem. Quisquam numquam aliquam sed eius amet neque eius. Numquam neque quaerat consectetur etincidunt.", "name": "Ut non quiquia neque velit dolor ut.", @@ -301,13 +301,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1607101200, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "oliviak", "deadline": { "$reql_type$": "TIME", "epoch_time": 1607965200, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Non ipsum adipisci non dolor sed quiquia. Dolorem magnam dolor quisquam velit voluptatem quaerat dolore. Dolorem quisquam ut ipsum. Aliquam quaerat numquam aliquam tempora consectetur aliquam. Neque tempora eius est quiquia modi. Non dolore labore ipsum tempora. Modi velit quisquam aliquam tempora dolorem. Sed neque magnam consectetur. Dolore porro non aliquam. Ipsum aliquam dolor numquam numquam.", "name": "Quiquia voluptatem dolor adipisci.", @@ -319,13 +319,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1604941200, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "rhysg", "deadline": { "$reql_type$": "TIME", "epoch_time": 1605805200, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Dolorem magnam amet non est magnam. Ipsum consectetur sed modi. Amet sed ipsum tempora. Porro est porro voluptatem. Numquam velit dolor tempora non. Dolorem quisquam amet ut adipisci sed quisquam.", "name": "Velit consectetur magnam amet dolore adipisci non numquam.", @@ -338,12 +338,12 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1604941200, - "timezone": "+07:00" + "timezone": "+00:00" }, "deadline": { "$reql_type$": "TIME", "epoch_time": 1611075600, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Ipsum dolorem porro eius ut. Quaerat dolore magnam sit consectetur labore eius ipsum. Quiquia dolore dolorem sit sed sit sed. Sed sit quaerat numquam adipisci. Ipsum aliquam est dolor est non numquam. Numquam porro aliquam dolorem etincidunt. Numquam etincidunt etincidunt non. Labore modi modi porro quisquam.", "id": "ee4af55a-cff3-4ffc-96ea-24c4b9979773", @@ -370,13 +370,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1607533200, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "alaricw", "deadline": { "$reql_type$": "TIME", "epoch_time": 1608397200, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Sed consectetur numquam ipsum ipsum. Quaerat aliquam magnam consectetur ut modi tempora quiquia. Aliquam eius tempora voluptatem sed numquam. Sed neque porro aliquam sit. Consectetur quaerat sed tempora aliquam.", "name": "Amet sit tempora neque dolor.", @@ -388,13 +388,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1605632400, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "julietc", "deadline": { "$reql_type$": "TIME", "epoch_time": 1606496400, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Quiquia numquam tempora aliquam ipsum eius quiquia. Dolorem voluptatem labore quiquia ipsum. Neque dolor quaerat quiquia dolor quisquam aliquam velit. Quiquia eius magnam numquam dolore. Neque ipsum quisquam dolor modi voluptatem.", "name": "Est ipsum dolor quisquam aliquam est tempora.", @@ -406,13 +406,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1604509200, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "alaricw", "deadline": { "$reql_type$": "TIME", "epoch_time": 1605373200, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Dolorem consectetur numquam ipsum modi. Ipsum porro adipisci est labore. Ipsum voluptatem est sit ut etincidunt neque aliquam. Quaerat tempora dolor quiquia dolorem. Sit dolore eius non consectetur porro aliquam porro. Etincidunt quiquia amet aliquam. Quisquam tempora ipsum dolore etincidunt. Labore consectetur amet modi sit neque. Tempora numquam dolore consectetur quisquam consectetur numquam sed.", "name": "Aliquam ipsum adipisci numquam voluptatem porro quisquam.", @@ -424,13 +424,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1608570000, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "lucyl", "deadline": { "$reql_type$": "TIME", "epoch_time": 1609434000, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Quiquia quaerat sed est quisquam. Quiquia porro sed sit labore dolore. Dolorem numquam sit magnam dolorem quisquam ut est. Ipsum amet voluptatem numquam est non. Amet eius dolor sit.", "name": "Aliquam adipisci numquam quiquia non non dolore est.", @@ -442,13 +442,13 @@ "created_on": { "$reql_type$": "TIME", "epoch_time": 1608570000, - "timezone": "+07:00" + "timezone": "+00:00" }, "creator": "alaricw", "deadline": { "$reql_type$": "TIME", "epoch_time": 1609434000, - "timezone": "+07:00" + "timezone": "+00:00" }, "description": "Consectetur non sed quaerat sed adipisci dolorem. Sed tempora quiquia quisquam quaerat dolor tempora ipsum. Non quaerat sit non etincidunt. Dolorem dolore consectetur sed. Neque non labore dolore ipsum ut labore. Etincidunt magnam velit magnam ut porro neque ipsum. Labore numquam dolor ipsum. Labore aliquam voluptatem amet dolore. Ut dolor ut sed modi velit labore aliquam. Voluptatem non ut porro.", "name": "Magnam velit est neque dolor dolor sed ipsum.",