Skip to main content

MacTime (aka WhenWhat or ww)

A Python tool for manipulating macOS file date attributes.

The Story

I've been organizing my files lately and noticed that there's no easy way to set the "Date Added" attribute to files in a folder. So I decided to write a library that makes it easy and accessible through both Python and CLI.

One of the weird goals when writing this project was to not have any dependencies and to be compatible with Python 3.9+, allowing it to run with macOS' built-in Python.

The code is a mixture of Claude work and mine.

Features

  • View and modify macOS file date attributes
  • No dependencies required
  • Supports Python 3.9+ (works with macOS built-in Python)
  • Multiple command aliases: mactime, whenwhat, or ww
  • Batch operations with recursive directory support
  • Fast.

Supported Date Attributes

MacTime supports viewing and modifying the following macOS file date attributes:

Attribute Shorthand Description Writable
created c  Date Created ✅
modified m  Date Modified ✅
accessed a Last accessed date ✅
added d  Date Added ✅
changed g Last attribute change date ⚠️ Always set to current time
backed_up b Last Backup Date ⚠️ Not affected by writings
opened o  Date Last Opened ❌ Read-only (stored in Spotlight)

Installation

UV

uv tool install mactime

pipx

pipx install mactime

Pure Python

bash <(curl -fSL https://raw.githubusercontent.com/Bobronium/mactime/refs/heads/main/install.sh)

pip

pip install mactime

Or simply clone and install from the repository:

cd mactime
pip install -e .

Command-Line Usage

Get File Attributes

View date attributes for a file:

mactime get /tmp/files -ri --order-by added --reversed --format finder
┌──────────────────┬──────────────────┬──────────────────┬──────────────────┬──────────────────┐
│ Name             │ Date Created     │ Date Modified    │ Date Last Opened │ Date Added       │
├──────────────────┼──────────────────┼──────────────────┼──────────────────┼──────────────────┤
│ /tmp/files       │ Today at 22:15   │ Today at 22:16   │ --               │ Today at 22:15   │
│ /tmp/files/1.txt │ Today at 22:16   │ Today at 22:16   │ --               │ Today at 22:16   │
│ /tmp/files/2.txt │ Today at 22:16   │ Today at 22:16   │ --               │ Today at 22:16   │
│ /tmp/files/3.txt │ Today at 22:16   │ Today at 22:16   │ --               │ Today at 22:16   │
└──────────────────┴──────────────────┴──────────────────┴──────────────────┴──────────────────┘

Get a specific attribute:

mactime get /tmp/files/1.txt modified
# Or using shorthand
mactime get /tmp/files/1.txt m

Set File Attributes

Set a specific date attribute:

# Set modification time to a specific date
mactime set file.txt -m "2023-06-15T14:30:00"

# Set creation date to now
mactime set file.txt -c now

# Set added date to yesterday
mactime set file.txt -d yesterday

# Reset to epoch (Jan 1, 1970)
mactime set file.txt -d epoch

Copy values from another attribute:

# Set creation date to match modification date
mactime set file.txt -c m

Set Multiple Files at Once

# Set all files in a directory
mactime set *.txt -m "2023-06-15T14:30:00"

# Recursively process all files in directories
mactime set ./documents -r -m "2023-06-15T14:30:00"

Transfer Attributes

Copy attributes from one file to another:

# Transfer modification date
mactime transfer source.txt target.txt -m

# Transfer all attributes
mactime transfer source.txt target.txt --all

# Transfer to multiple targets
mactime transfer source.txt target1.txt target2.txt -m

# Transfer recursively to files in a directory
mactime transfer source.txt ./dir -r --all

Reset Attributes

Reset attributes to epoch (Jan 1, 1970):

# Reset modification and creation times
mactime reset file.txt -m -c

# Reset all attributes
mactime reset file.txt --all

# Reset all files in a directory recursively
mactime reset ./dir -r --all

Python API Usage

from mactime.core import get_timespec_attrs, set_path_times, modify_macos_times
from datetime import datetime


# Get all attributes
attrs = get_timespec_attrs("file.txt")
print(f"Created: {attrs['created']}")
print(f"Modified: {attrs['modified']}")
print(f"Added: {attrs['added']}")

# Set specific attributes
modify_macos_times(
    "file.txt",
    created=datetime(2023, 6, 15, 14, 30, 0),
    modified=datetime.now()
)

# Set added date to match creation date
attrs = get_timespec_attrs("file.txt")
set_path_times("file.txt", to_set={}, from_another_attributes={"added": "created"})

# Process multiple files
from mactime.core import resolve_paths


modified = datetime.now()
for file in resolve_paths(["./documents"], recursive=True, include_root=True):
    modify_macos_times(file, modified=modified)

Limitations

  • macOS Only: This tool uses macOS-specific system calls and will not work on other operating systems.
  • Some Attributes Are Read-Only:
    • opened is stored in Spotlight index and cannot be modified.
    • backed_up is ignored by the system calls.
    • changed is always updated to the current time when attributes are modified.
  • System Permissions: Modifying some file attributes may require elevated permissions.

How It Works

MacTime uses the low-level setattrlist and getattrlist C functions via Python's ctypes library to interact directly with the macOS file system. This approach avoids dependencies and provides direct access to file metadata that is not accessible through standard Python libraries.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

Distributed under the MIT License. See LICENSE for more information.

Acknowledgements

This project was inspired by a Stack Overflow discussion about manipulating macOS file attributes.

Behavior Notes

Creation Time Auto-Adjustment

When setting the modification time (-m) without explicitly setting the creation time (-c) and new modification time is before current creation time, both will be set to new modification time:

# This will set both modification AND creation time to "2023-06-15T14:30:00"
# if the current creation time is newer than this date
mactime set file.txt -m "2023-06-15T14:30:00"

# This preserves the original creation time regardless of dates
mactime set file.txt -m "2023-06-15T14:30:00" -c c

To preserve the original creation time when setting the modification time, explicitly reference the current creation time with -c c.

Metadata

Release files for mactime 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mactime 0.1.0
File Size Uploaded Provenance
mactime-0.1.0.tar.gz 123.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mactime 0.1.0
File Interpreter ABI Platform
mactime-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 148.1 kB

Release files / mactime-0.1.0.tar.gz

Download URL mactime-0.1.0.tar.gz
Size 123.4 kB
Tags Source
SHA-256 checksum
How to use checksums
d5c8626f9177d8974986111cf8a77b2340d60243fd5fe6822ae7d152ba713d3e
BLAKE2b-256 checksum
How to use checksums
fb77c6f53e0edf50e55f47e3a70150346401b43bec8e9799fa7b92a65698810e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.5.24

Release files / mactime-0.1.0-py3-none-any.whl

Download URL mactime-0.1.0-py3-none-any.whl
Size 24.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
acbdbc298890f205291907715314b5f464246ceeabb82d6cd3c8453a95be340c
BLAKE2b-256 checksum
How to use checksums
6f14c7e685e0784d68dcce5146a14d8896f6a10a7b61ea69e013832aa4453cbc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.5.24

Security for mactime 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page