Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 66 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,72 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.0.0b1] - 2025-10-24
## [1.0.0b3]

### Fixed

- Fix Python 3.14 compatibility issue in `move_frame()` method where `Fraction()` constructor with two arguments failed due to stricter type requirements

修复 Python 3.14 兼容性问题,`move_frame()` 方法中 `Fraction()` 构造函数因更严格的类型要求而失败

- Fix precision loss issues in timecode initialization methods (`__init_smpte()`, `__init_frame()`) by using `Fraction()` division instead of float division

修复时码初始化方法中的精度损失问题,使用 `Fraction()` 除法替代浮点数除法

- Fix FCPX format output to correctly handle integer timestamps, avoiding large numerator values when the result is a whole number

修复 FCPX 格式输出,正确处理整数时间戳,避免结果为整数时出现大分子值

### Added

- Add `move_frame()` and `move_time()` methods to DfttTimecode class for moving timecode by specified frames or time duration

为 DfttTimecode 类添加 `move_frame()` 和 `move_time()` 方法,用于按指定帧数或时间段移动时码

- Add comprehensive unit tests (32 tests) for `move_frame()` and `move_time()` methods

为 `move_frame()` 和 `move_time()` 方法添加全面的单元测试(32 个测试)

- Frame movement tests: forward/backward movement, zero movement, large movements (86400 frames)

帧移动测试:正向/反向移动、零移动、大规模移动(86400 帧)

- Time movement tests: float/int/Fraction input support, various time movements

时间移动测试:浮点数/整数/分数输入支持、各种时间移动

- Strict mode tests: 24-hour cycling behavior verification

严格模式测试:24 小时循环行为验证

- Different frame rates: 24, 30, 60, 119.88 fps

不同帧率:24、30、60、119.88 fps

- Drop-frame timecode support tests

丢帧时码支持测试

- Method chaining and input validation tests

方法链和输入验证测试

- Equivalence test between `move_frame()` and `move_time()`

`move_frame()` 和 `move_time()` 的等价性测试

### Changed

- Improved internal timestamp precision across the entire codebase by consistently using `Fraction()` arithmetic

通过始终使用 `Fraction()` 算术运算,提高整个代码库的内部时间戳精度

## [1.0.0b2]
### Fixed
- Fix bug for fcpx output format
修复 fcpx 输出格式的错误

## [1.0.0b1]

### Summary

Expand Down
94 changes: 77 additions & 17 deletions dftt_timecode/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@
01:00:04:04
"""

from dftt_timecode.core.dftt_timecode import DfttTimecode
from fractions import Fraction
from typing import Optional
from dftt_timecode.core.dftt_timecode import DfttTimecode, TimecodeType
from dftt_timecode.core.dftt_timerange import DfttTimeRange
from dftt_timecode.logging_config import configure_logging, get_logger

# Read version from package metadata (populated from pyproject.toml)
try:
from importlib.metadata import version, PackageNotFoundError

try:
__version__ = version("dftt-timecode")
except PackageNotFoundError:
Expand All @@ -43,7 +46,13 @@


# Aliases for easier importing
def timecode(*args, **kwargs) -> DfttTimecode:
def Timecode(
timecode_value,
timecode_type: TimecodeType = "auto",
fps=24.0,
drop_frame=None,
strict=True,
) -> DfttTimecode:
"""Create a DfttTimecode instance.

This is an alias for :class:`DfttTimecode` constructor.
Expand All @@ -56,12 +65,26 @@ def timecode(*args, **kwargs) -> DfttTimecode:
DfttTimecode: A new timecode instance

Example:
>>> tc = timecode('01:00:00:00', fps=24)
>>> tc = Timecode('01:00:00:00', fps=24)
"""
return DfttTimecode(*args, **kwargs)


def timerange(*args, **kwargs) -> DfttTimeRange:
return DfttTimecode(
timecode_value,
timecode_type=timecode_type,
fps=fps,
drop_frame=drop_frame,
strict=strict,
)


def Timerange(
start_tc=None,
end_tc=None,
forward: bool = True,
fps=24.0,
start_precise_time: Optional[Fraction] = None,
precise_duration: Optional[Fraction] = None,
strict_24h: bool = False,
) -> DfttTimeRange:
"""Create a DfttTimeRange instance.

This is an alias for :class:`DfttTimeRange` constructor.
Expand All @@ -74,12 +97,26 @@ def timerange(*args, **kwargs) -> DfttTimeRange:
DfttTimeRange: A new timerange instance

Example:
>>> tr = timerange('01:00:00:00', '02:00:00:00', fps=24)
>>> tr = Timerange('01:00:00:00', '02:00:00:00', fps=24)
"""
return DfttTimeRange(*args, **kwargs)


def dtc(*args, **kwargs) -> DfttTimecode:
return DfttTimeRange(
start_tc=start_tc,
end_tc=end_tc,
fps=fps,
forward=forward,
start_precise_time=start_precise_time,
precise_duration=precise_duration,
strict_24h=strict_24h,
)


def dtc(
timecode_value,
timecode_type: TimecodeType = "auto",
fps=24.0,
drop_frame=None,
strict=True,
) -> DfttTimecode:
"""Create a DfttTimecode instance (short alias).

This is a short alias for :class:`DfttTimecode` constructor.
Expand All @@ -94,10 +131,24 @@ def dtc(*args, **kwargs) -> DfttTimecode:
Example:
>>> tc = dtc('01:00:00:00', fps=24)
"""
return DfttTimecode(*args, **kwargs)


def dtr(*args, **kwargs) -> DfttTimeRange:
return DfttTimecode(
timecode_value,
timecode_type=timecode_type,
fps=fps,
drop_frame=drop_frame,
strict=strict,
)


def dtr(
start_tc=None,
end_tc=None,
forward: bool = True,
fps=24.0,
start_precise_time: Optional[Fraction] = None,
precise_duration: Optional[Fraction] = None,
strict_24h: bool = False,
) -> DfttTimeRange:
"""Create a DfttTimeRange instance (short alias).

This is a short alias for :class:`DfttTimeRange` constructor.
Expand All @@ -112,7 +163,16 @@ def dtr(*args, **kwargs) -> DfttTimeRange:
Example:
>>> tr = dtr('01:00:00:00', '02:00:00:00', fps=24)
"""
return DfttTimeRange(*args, **kwargs)
return DfttTimeRange(
start_tc=start_tc,
end_tc=end_tc,
fps=fps,
forward=forward,
start_precise_time=start_precise_time,
precise_duration=precise_duration,
strict_24h=strict_24h,
)


name = "dftt_timecode"
__author__ = "You Ziyuan"
Expand Down
Loading