Add snowflake_time utility (#105)
Some checks failed
Deploy MkDocs / deploy (push) Has been cancelled
Some checks failed
Deploy MkDocs / deploy (push) Has been cancelled
This commit is contained in:
parent
87d67eb63b
commit
3437050f0e
@ -51,7 +51,7 @@ from .errors import (
|
|||||||
NotFound,
|
NotFound,
|
||||||
)
|
)
|
||||||
from .color import Color
|
from .color import Color
|
||||||
from .utils import escape_markdown, escape_mentions, message_pager, utcnow
|
from .utils import escape_markdown, escape_mentions, message_pager, utcnow, snowflake_time
|
||||||
from .enums import (
|
from .enums import (
|
||||||
GatewayIntent,
|
GatewayIntent,
|
||||||
GatewayOpcode,
|
GatewayOpcode,
|
||||||
@ -153,6 +153,7 @@ __all__ = [
|
|||||||
"escape_markdown",
|
"escape_markdown",
|
||||||
"escape_mentions",
|
"escape_mentions",
|
||||||
"message_pager",
|
"message_pager",
|
||||||
|
"snowflake_time",
|
||||||
"GatewayIntent",
|
"GatewayIntent",
|
||||||
"GatewayOpcode",
|
"GatewayOpcode",
|
||||||
"ButtonStyle",
|
"ButtonStyle",
|
||||||
|
@ -6,6 +6,9 @@ from datetime import datetime, timezone
|
|||||||
from typing import Any, AsyncIterator, Dict, Optional, TYPE_CHECKING
|
from typing import Any, AsyncIterator, Dict, Optional, TYPE_CHECKING
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
# Discord epoch in milliseconds (2015-01-01T00:00:00Z)
|
||||||
|
DISCORD_EPOCH = 1420070400000
|
||||||
|
|
||||||
if TYPE_CHECKING: # pragma: no cover - for type hinting only
|
if TYPE_CHECKING: # pragma: no cover - for type hinting only
|
||||||
from .models import Message, TextChannel
|
from .models import Message, TextChannel
|
||||||
|
|
||||||
@ -15,6 +18,24 @@ def utcnow() -> datetime:
|
|||||||
return datetime.now(timezone.utc)
|
return datetime.now(timezone.utc)
|
||||||
|
|
||||||
|
|
||||||
|
def snowflake_time(snowflake: int) -> datetime:
|
||||||
|
"""Return the creation time of a Discord snowflake.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
snowflake:
|
||||||
|
The snowflake ID to convert.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
datetime
|
||||||
|
The UTC timestamp embedded in the snowflake.
|
||||||
|
"""
|
||||||
|
|
||||||
|
timestamp_ms = (snowflake >> 22) + DISCORD_EPOCH
|
||||||
|
return datetime.fromtimestamp(timestamp_ms / 1000, tz=timezone.utc)
|
||||||
|
|
||||||
|
|
||||||
async def message_pager(
|
async def message_pager(
|
||||||
channel: "TextChannel",
|
channel: "TextChannel",
|
||||||
*,
|
*,
|
||||||
|
20
docs/utils.md
Normal file
20
docs/utils.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Utility Helpers
|
||||||
|
|
||||||
|
Disagreement provides a few small utility functions for working with Discord data.
|
||||||
|
|
||||||
|
## `utcnow`
|
||||||
|
|
||||||
|
Returns the current timezone-aware UTC `datetime`.
|
||||||
|
|
||||||
|
## `snowflake_time`
|
||||||
|
|
||||||
|
Converts a Discord snowflake ID into the UTC timestamp when it was generated.
|
||||||
|
|
||||||
|
```python
|
||||||
|
from disagreement.utils import snowflake_time
|
||||||
|
|
||||||
|
created_at = snowflake_time(175928847299117063)
|
||||||
|
print(created_at.isoformat())
|
||||||
|
```
|
||||||
|
|
||||||
|
The function extracts the timestamp from the snowflake and returns a `datetime` in UTC.
|
@ -62,4 +62,5 @@ nav:
|
|||||||
- 'Mentions': 'mentions.md'
|
- 'Mentions': 'mentions.md'
|
||||||
- 'OAuth2': 'oauth2.md'
|
- 'OAuth2': 'oauth2.md'
|
||||||
- 'Presence': 'presence.md'
|
- 'Presence': 'presence.md'
|
||||||
- 'Voice Client': 'voice_client.md'
|
- 'Voice Client': 'voice_client.md'
|
||||||
|
- 'Utility Helpers': 'utils.md'
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
from datetime import timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
from disagreement.utils import escape_markdown, escape_mentions, utcnow
|
from disagreement.utils import (
|
||||||
|
escape_markdown,
|
||||||
|
escape_mentions,
|
||||||
|
utcnow,
|
||||||
|
snowflake_time
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_utcnow_timezone():
|
def test_utcnow_timezone():
|
||||||
@ -8,6 +13,13 @@ def test_utcnow_timezone():
|
|||||||
assert now.tzinfo == timezone.utc
|
assert now.tzinfo == timezone.utc
|
||||||
|
|
||||||
|
|
||||||
|
def test_snowflake_time():
|
||||||
|
dt = datetime(2020, 1, 1, tzinfo=timezone.utc)
|
||||||
|
ms = int(dt.timestamp() * 1000) - 1420070400000
|
||||||
|
snowflake = ms << 22
|
||||||
|
assert snowflake_time(snowflake) == dt
|
||||||
|
|
||||||
|
|
||||||
def test_escape_markdown():
|
def test_escape_markdown():
|
||||||
text = "**bold** _under_ ~strike~ `code` > quote | pipe"
|
text = "**bold** _under_ ~strike~ `code` > quote | pipe"
|
||||||
escaped = escape_markdown(text)
|
escaped = escape_markdown(text)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user