Utility class for working with POSIX timestamps in milliseconds.
Project description
milliseconds
A lightweight, POSIX-compliant utility library for working with timestamps in milliseconds.
Features
- Convert between datetime and milliseconds - Easy conversion to/from Python datetime objects
- Floor and ceil operations - Round timestamps to specific time boundaries (second, minute, hour, day)
- Boundary navigation - Jump to next/previous time boundaries
- Validation - Check if timestamps align to specific time units
- Arithmetic operations - Increment/decrement by seconds, minutes, hours, or days
- Comparison utilities - Check if timestamps fall within the same time period
- Full POSIX compliance - Supports negative timestamps (dates before 1970-01-01)
- Zero dependencies - Only uses Python standard library
- Type hints - Fully typed for better IDE support
Table of Contents
Installation
pip install milliseconds
Quick Start
from datetime import datetime
from zoneinfo import ZoneInfo
from milliseconds import milliseconds, constants
# Convert datetime to milliseconds
dt = datetime(2024, 1, 1, 12, 30, 45, tzinfo=ZoneInfo("UTC"))
ms = milliseconds.milliseconds(dt)
print(ms) # 1704113445000
# Convert back to datetime
dt_back = milliseconds.time(ms, ZoneInfo("UTC"))
print(dt_back) # 2024-01-01 12:30:45+00:00
# Floor to nearest hour
floored = milliseconds.floor(ms, constants.hour)
print(milliseconds.time(floored, ZoneInfo("UTC"))) # 2024-01-01 12:00:00+00:00
# Get next day boundary
next_day = milliseconds.next_day(ms)
print(milliseconds.time(next_day, ZoneInfo("UTC"))) # 2024-01-02 00:00:00+00:00
Usage Examples
Basic Conversion
from datetime import datetime
from zoneinfo import ZoneInfo
from milliseconds import milliseconds
# DateTime to milliseconds
dt = datetime(2024, 6, 15, 14, 30, 0, tzinfo=ZoneInfo("UTC"))
ms = milliseconds.milliseconds(dt)
print(ms) # 1718460600000
# Milliseconds to datetime
dt_back = milliseconds.time(ms, ZoneInfo("America/New_York"))
print(dt_back) # 2024-06-15 10:30:00-04:00 (EDT)
Floor and Ceil Operations
from milliseconds import milliseconds, constants
timestamp = 1704113445789 # 2024-01-01 12:30:45.789
# Floor operations (round down)
print(milliseconds.floor(timestamp, constants.second)) # 1704113445000 (12:30:45.000)
print(milliseconds.floor(timestamp, constants.minute)) # 1704113400000 (12:30:00.000)
print(milliseconds.floor(timestamp, constants.hour)) # 1704110400000 (12:00:00.000)
print(milliseconds.floor(timestamp, constants.day)) # 1704067200000 (00:00:00.000)
# Ceil operations (round up)
print(milliseconds.ceil(timestamp, constants.second)) # 1704113446000 (12:30:46.000)
print(milliseconds.ceil(timestamp, constants.minute)) # 1704113460000 (12:31:00.000)
print(milliseconds.ceil(timestamp, constants.hour)) # 1704114000000 (13:00:00.000)
Boundary Navigation
from milliseconds import milliseconds
timestamp = 1704113445789 # 2024-01-01 12:30:45.789
# Navigate to previous boundaries
print(milliseconds.last_second(timestamp)) # Previous second: 12:30:44.000
print(milliseconds.last_minute(timestamp)) # Previous minute: 12:29:00.000
print(milliseconds.last_hour(timestamp)) # Previous hour: 11:00:00.000
print(milliseconds.last_day(timestamp)) # Previous day: 2023-12-31 00:00:00
# Navigate to next boundaries
print(milliseconds.next_second(timestamp)) # Next second: 12:30:46.000
print(milliseconds.next_minute(timestamp)) # Next minute: 12:31:00.000
print(milliseconds.next_hour(timestamp)) # Next hour: 13:00:00.000
print(milliseconds.next_day(timestamp)) # Next day: 2024-01-02 00:00:00
Time Arithmetic
from milliseconds import milliseconds
timestamp = 1704067200000 # 2024-01-01 00:00:00
# Increment operations
plus_30_sec = milliseconds.increment_second(timestamp, 30)
plus_15_min = milliseconds.increment_minute(timestamp, 15)
plus_6_hours = milliseconds.increment_hour(timestamp, 6)
plus_7_days = milliseconds.increment_day(timestamp, 7)
# Decrement operations
minus_30_sec = milliseconds.decrement_second(timestamp, 30)
minus_15_min = milliseconds.decrement_minute(timestamp, 15)
minus_6_hours = milliseconds.decrement_hour(timestamp, 6)
minus_7_days = milliseconds.decrement_day(timestamp, 7)
# Fractional values are supported
plus_half_hour = milliseconds.increment_hour(timestamp, 0.5)
minus_quarter_day = milliseconds.decrement_day(timestamp, 0.25)
Validation
from milliseconds import milliseconds
# Check if timestamp aligns to boundaries
timestamp = 1704110400000 # 2024-01-01 12:00:00.000
print(milliseconds.is_valid_second(timestamp)) # True (no milliseconds)
print(milliseconds.is_valid_minute(timestamp)) # True (no seconds)
print(milliseconds.is_valid_hour(timestamp)) # True (no minutes)
print(milliseconds.is_valid_day(timestamp)) # False (not midnight UTC)
timestamp_with_ms = 1704110400500 # 12:00:00.500
print(milliseconds.is_valid_second(timestamp_with_ms)) # False (has milliseconds)
Comparison
from milliseconds import milliseconds
ts1 = 1704110455100 # 2024-01-01 12:00:55.100
ts2 = 1704110455900 # 2024-01-01 12:00:55.900
ts3 = 1704110460000 # 2024-01-01 12:01:00.000
# Check if timestamps are in the same period
print(milliseconds.is_same_second(ts1, ts2)) # True (both in second :55)
print(milliseconds.is_same_second(ts2, ts3)) # False (different seconds)
print(milliseconds.is_same_minute(ts1, ts3)) # True (both in minute 12:00)
print(milliseconds.is_same_hour(ts1, ts3)) # True (both in hour 12:00)
print(milliseconds.is_same_day(ts1, ts3)) # True (both on 2024-01-01)
Working with Negative Timestamps
POSIX timestamps support dates before the Unix epoch (1970-01-01). This library handles them correctly:
from datetime import datetime
from zoneinfo import ZoneInfo
from milliseconds import milliseconds
# Create a date before 1970
dt = datetime(1969, 12, 31, 23, 0, 0, tzinfo=ZoneInfo("UTC"))
ms = milliseconds.milliseconds(dt)
print(ms) # -3600000
# Operations work correctly
last_hour = milliseconds.last_hour(ms)
print(milliseconds.time(last_hour, ZoneInfo("UTC"))) # 1969-12-31 22:00:00
# Arithmetic works naturally
earlier = milliseconds.decrement_day(ms, 1)
print(milliseconds.time(earlier, ZoneInfo("UTC"))) # 1969-12-30 23:00:00
API Reference
Constants
The constants IntEnum provides time unit values in milliseconds:
from milliseconds import constants
constants.second # 1_000 - Milliseconds in one second
constants.minute # 60_000 - Milliseconds in one minute
constants.hour # 3_600_000 - Milliseconds in one hour
constants.day # 86_400_000 - Milliseconds in one day
Conversion Methods
milliseconds(time: datetime) -> int- Convert datetime to millisecondstime(milliseconds: int, timezone: ZoneInfo) -> datetime- Convert milliseconds to datetime
Rounding Methods
floor(milliseconds: int, factor: int = constants.hour) -> int- Round down to nearest factorceil(milliseconds: int, factor: int = constants.hour) -> int- Round up to nearest factor
Boundary Navigation
last_second(timestamp: int) -> int- Get start of previous secondnext_second(timestamp: int) -> int- Get start of next secondlast_minute(timestamp: int) -> int- Get start of previous minutenext_minute(timestamp: int) -> int- Get start of next minutelast_hour(timestamp: int) -> int- Get start of previous hournext_hour(timestamp: int) -> int- Get start of next hourlast_day(timestamp: int) -> int- Get start of previous day (UTC)next_day(timestamp: int) -> int- Get start of next day (UTC)
Validation Methods
is_valid_second(timestamp: int) -> bool- Check if aligned to second boundaryis_valid_minute(timestamp: int) -> bool- Check if aligned to minute boundaryis_valid_hour(timestamp: int) -> bool- Check if aligned to hour boundaryis_valid_day(timestamp: int) -> bool- Check if aligned to day boundary
Arithmetic Methods
increment_second(timestamp: int, n: float = 1) -> int- Add secondsdecrement_second(timestamp: int, n: float = 1) -> int- Subtract secondsincrement_minute(timestamp: int, n: float = 1) -> int- Add minutesdecrement_minute(timestamp: int, n: float = 1) -> int- Subtract minutesincrement_hour(timestamp: int, n: float = 1) -> int- Add hoursdecrement_hour(timestamp: int, n: float = 1) -> int- Subtract hoursincrement_day(timestamp: int, n: float = 1) -> int- Add daysdecrement_day(timestamp: int, n: float = 1) -> int- Subtract days
Comparison Methods
is_same_second(ts1: int, ts2: int) -> bool- Check if in same secondis_same_minute(ts1: int, ts2: int) -> bool- Check if in same minuteis_same_hour(ts1: int, ts2: int) -> bool- Check if in same houris_same_day(ts1: int, ts2: int) -> bool- Check if in same day (UTC)
License
milliseconds is distributed under the terms of the MIT license.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file milliseconds-0.1.2.tar.gz.
File metadata
- Download URL: milliseconds-0.1.2.tar.gz
- Upload date:
- Size: 9.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4209ef5c306628ca335c07f10af54f5873e3de7adfe612630cb1addd600b1b9b
|
|
| MD5 |
478d4426a35ab4532ce8eeb7616f60d7
|
|
| BLAKE2b-256 |
2a77c17b1ef4bb8cbe2e1280822411d486f6b294ecaf560fd2d2fb4d02d7775b
|
File details
Details for the file milliseconds-0.1.2-py3-none-any.whl.
File metadata
- Download URL: milliseconds-0.1.2-py3-none-any.whl
- Upload date:
- Size: 8.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d82f781f8f90f545017478f011697d072794314a97f18e9d8d493e55b22b4fc6
|
|
| MD5 |
11314d30e1a0f7ec31fa540eb1fb5fc4
|
|
| BLAKE2b-256 |
5313418c5eaba0c610996ed3c6e1b54d80f17f8270c49574159fdb25799311c9
|