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,
|
||||
)
|
||||
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",
|
||||
|
@ -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
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.
|
@ -63,3 +63,4 @@ nav:
|
||||
- 'OAuth2': 'oauth2.md'
|
||||
- 'Presence': 'presence.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():
|
||||
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user