Add snowflake_time utility (#105)
Some checks failed
Deploy MkDocs / deploy (push) Has been cancelled

This commit is contained in:
Slipstream 2025-06-15 18:52:38 -06:00 committed by GitHub
parent 87d67eb63b
commit 3437050f0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 59 additions and 4 deletions

View File

@ -51,7 +51,7 @@ from .errors import (
NotFound,
)
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 (
GatewayIntent,
GatewayOpcode,
@ -153,6 +153,7 @@ __all__ = [
"escape_markdown",
"escape_mentions",
"message_pager",
"snowflake_time",
"GatewayIntent",
"GatewayOpcode",
"ButtonStyle",

View File

@ -6,6 +6,9 @@ from datetime import datetime, timezone
from typing import Any, AsyncIterator, Dict, Optional, TYPE_CHECKING
import re
# Discord epoch in milliseconds (2015-01-01T00:00:00Z)
DISCORD_EPOCH = 1420070400000
if TYPE_CHECKING: # pragma: no cover - for type hinting only
from .models import Message, TextChannel
@ -15,6 +18,24 @@ def utcnow() -> datetime:
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(
channel: "TextChannel",
*,

20
docs/utils.md Normal file
View 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.

View File

@ -62,4 +62,5 @@ nav:
- 'Mentions': 'mentions.md'
- 'OAuth2': 'oauth2.md'
- 'Presence': 'presence.md'
- 'Voice Client': 'voice_client.md'
- 'Voice Client': 'voice_client.md'
- 'Utility Helpers': 'utils.md'

View File

@ -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():
@ -8,6 +13,13 @@ def test_utcnow_timezone():
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():
text = "**bold** _under_ ~strike~ `code` > quote | pipe"
escaped = escape_markdown(text)