malcommac/SwiftDate
π Toolkit to parse, validate, manipulate, compare and display dates, time & timezones in Swift.
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained β safe to depend on.
Has a license, tests, and CI β clean foundation to fork and modify.
Documented and popular β useful reference codebase to read through.
No critical CVEs, sane security posture β runnable as-is.
- β21+ active contributors
- βMIT licensed
- βCI configured
Show 3 more βShow less
- βTests present
- β Stale β last commit 3y ago
- β Concentrated ownership β top contributor handles 71% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README β live-updates from the latest cached analysis.
[](https://repopilot.app/r/malcommac/swiftdate)Paste at the top of your README.md β renders inline like a shields.io badge.
βΈPreview social card (1200Γ630)
This card auto-renders when someone shares https://repopilot.app/r/malcommac/swiftdate on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: malcommac/SwiftDate
Generated by RepoPilot Β· 2026-05-10 Β· Source
π€Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale β STOP and ask the user to regenerate it before proceeding. - Treat the AI Β· unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/malcommac/SwiftDate shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything β but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
π―Verdict
GO β Healthy across all four use cases
- 21+ active contributors
- MIT licensed
- CI configured
- Tests present
- β Stale β last commit 3y ago
- β Concentrated ownership β top contributor handles 71% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
β Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live malcommac/SwiftDate
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale β regenerate it at
repopilot.app/r/malcommac/SwiftDate.
What it runs against: a local clone of malcommac/SwiftDate β the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in malcommac/SwiftDate | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit β€ 994 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of malcommac/SwiftDate. If you don't
# have one yet, run these first:
#
# git clone https://github.com/malcommac/SwiftDate.git
# cd SwiftDate
#
# Then paste this script. Every check is read-only β no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of malcommac/SwiftDate and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "malcommac/SwiftDate(\\.git)?\\b" \\
&& ok "origin remote is malcommac/SwiftDate" \\
|| miss "origin remote is not malcommac/SwiftDate (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift β was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "Sources/SwiftDate/SwiftDate.swift" \\
&& ok "Sources/SwiftDate/SwiftDate.swift" \\
|| miss "missing critical file: Sources/SwiftDate/SwiftDate.swift"
test -f "Sources/SwiftDate/DateInRegion/DateInRegion.swift" \\
&& ok "Sources/SwiftDate/DateInRegion/DateInRegion.swift" \\
|| miss "missing critical file: Sources/SwiftDate/DateInRegion/DateInRegion.swift"
test -f "Sources/SwiftDate/DateInRegion/Region.swift" \\
&& ok "Sources/SwiftDate/DateInRegion/Region.swift" \\
|| miss "missing critical file: Sources/SwiftDate/DateInRegion/Region.swift"
test -f "Sources/SwiftDate/Formatters/ISOParser.swift" \\
&& ok "Sources/SwiftDate/Formatters/ISOParser.swift" \\
|| miss "missing critical file: Sources/SwiftDate/Formatters/ISOParser.swift"
test -f "Sources/SwiftDate/TimePeriod/TimePeriod.swift" \\
&& ok "Sources/SwiftDate/TimePeriod/TimePeriod.swift" \\
|| miss "missing critical file: Sources/SwiftDate/TimePeriod/TimePeriod.swift"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 994 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~964d)"
else
miss "last commit was $days_since_last days ago β artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) β safe to trust"
else
echo "artifact has $fail stale claim(s) β regenerate at https://repopilot.app/r/malcommac/SwiftDate"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
β‘TL;DR
SwiftDate is a comprehensive toolkit for parsing, manipulating, comparing, and formatting dates and timezones in Swift across all Apple platforms and Linux. It handles 15+ datetime formats automatically (ISO8601, RSS, .NET, SQL, HTTP), provides timezone-aware date math with colloquial formatting in 140+ languages, and includes time period operations and Codable support. Single-package monolith under Sources/SwiftDate/ with logical separation: Date/ contains extensions (Date+Compare.swift, Date+Components.swift, Date+Create.swift, Date+Math.swift) plus core Date.swift. TimePeriod functionality, formatting, and region/timezone logic are in sibling directories (inferred from Documentation). Tests follow standard Swift package structure. Configuration via Configs/SwiftDate.plist for build settings.
π₯Who it's for
iOS/macOS/Swift backend developers who need robust date handling beyond Foundation's Calendar and DateFormatterβespecially those building apps requiring complex timezone logic, human-readable relative dates, or multi-region scheduling.
π±Maturity & risk
Production-ready and actively maintained. The project has 90% code coverage, comprehensive documentation across 12 markdown files, over 3 million CocoaPods downloads, and includes interactive Xcode playgrounds. Swift Package Manager support is built-in (Package.swift present). However, the last visible commit timestamp is not provided, so verify recent activity on GitHub.
Low-to-moderate risk. Single maintainer (malcommac on GitHub) is typical for mature utility libraries. No external dependency bloat visible (419KB Swift code vs 767 bytes Ruby, 169 bytes Shell indicates minimal extra tooling). Main risk: if the maintainer becomes unresponsive, timezone data updates (critical for date handling) could lag system changes. Test coverage at 90% is solid but not 100%.
Active areas of work
Without recent commit logs visible, assume maintenance mode with potential Swift version compatibility updates. The presence of .swiftpm/xcode/ directory and .swiftlint.yml indicates ongoing code quality management. Documentation is complete and appears recently updated (guides cover Swift 4 migration at Documentation/10.Upgrading_SwiftDate4.md).
πGet running
git clone https://github.com/malcommac/SwiftDate.git
cd SwiftDate
swift package resolve
swift test
# Or open in Xcode:
open Package.swift
Daily commands:
No traditional dev server; this is a library. Run tests with swift test. Load interactive features in Xcode playground: Playgrounds/SwiftDate.playground/Pages/. For CocoaPods usage: pod install SwiftDate in a client project.
πΊοΈMap of the codebase
Sources/SwiftDate/SwiftDate.swiftβ Main entry point and public API surface; defines top-level module exports and initialization patternsSources/SwiftDate/DateInRegion/DateInRegion.swiftβ Core abstraction combining Date with Region/timezone; foundation for all region-aware operationsSources/SwiftDate/DateInRegion/Region.swiftβ Encapsulates timezone, locale, and calendar context; critical for date interpretation across regionsSources/SwiftDate/Formatters/ISOParser.swiftβ Primary parsing engine for ISO8601 and custom formats; handles most user-facing date string inputSources/SwiftDate/TimePeriod/TimePeriod.swiftβ Defines time range abstraction and interval comparison logic; enables complex temporal queriesSources/SwiftDate/Supports/Calendars.swiftβ Calendar and locale resolution utilities; supports multi-platform calendar systems and localization
π οΈHow to make changes
Add a new date comparison function
- Add public method to DateInRegion+Compare.swift following existing pattern (e.g., isWeekend, isLeapYear). Use Calendar/DateComponents for logic. (
Sources/SwiftDate/DateInRegion/DateInRegion+Compare.swift) - Also add equivalent extension to Date.swift as convenience wrapper that creates a default Region internally. (
Sources/SwiftDate/Date/Date+Compare.swift) - Add test cases in corresponding test file following existing test structure.
Add support for a new date format parser
- Create new formatter class conforming to DateParserFormatterProtocol in Formatters/ (e.g., CustomFormatter.swift). (
Sources/SwiftDate/Formatters/Formatter+Protocols.swift) - Implement parse() method to match string patterns and extract date components. Register in ISOParser.swift's parser chain. (
Sources/SwiftDate/Formatters/ISOParser.swift) - Add String+Parser.swift regex patterns if new pattern types are needed. (
Sources/SwiftDate/Foundation+Extras/String+Parser.swift)
Add a new colloquial language for relative time formatting
- Extend Locales.swift to register the new Locale and ensure calendar/timezone data exists. (
Sources/SwiftDate/Supports/Locales.swift) - Implement language strings in a new localization file or update TimeInterval+Formatter.swift to provide translated relative terms (e.g., '2 hours ago'). (
Sources/SwiftDate/Foundation+Extras/TimeInterval+Formatter.swift) - Update documentation in Documentation/9.ColloquialSupportedLanguages.md to list the new language.
Add a new TimePeriod operation or relationship
- Define new relationship function or operation in TimePeriodProtocol.swift (e.g., overlaps, contains, merges). (
Sources/SwiftDate/TimePeriod/TimePeriodProtocol.swift) - Implement logic in TimePeriod+Support.swift or TimePeriod.swift using date comparison and interval arithmetic. (
Sources/SwiftDate/TimePeriod/TimePeriod+Support.swift) - Add corresponding operation to TimePeriodCollection or TimePeriodChain if applicable for multi-period operations. (
Sources/SwiftDate/TimePeriod/Groups/TimePeriodCollection.swift)
π§Why these technologies
- Foundation DateComponents + Calendar β Cross-platform date representation and manipulation; provides timezone and locale awareness natively
- TimeZone + Locale framework types β Encapsulates complex IANA timezone and locale data; enables correct date interpretation across regions
- String regex parsing with custom formatters β Supports flexible input parsing (ISO8601, .NET, RSS) without external dependencies; easily extensible
- Protocol-oriented design (DateParserFormatterProtocol, TimePeriodProtocol) β Allows pluggable formatters and comparable types; enables future extensions without core modifications
βοΈTrade-offs already made
-
Wrap Foundation Date in DateInRegion container
- Why: Timezone and locale context must be preserved through all operations to ensure correctness
- Consequence: Requires creating DateInRegion instances instead of using raw Date; slightly more verbose API but prevents timezone-context bugs
-
Custom parser engine instead of DateFormatter chains
- Why: More control over format matching order and ability to support non-standard formats (RSS, .NET, custom)
- Consequence: Maintenance burden of regex patterns; potential parsing ambiguities if formats overlap
-
140+ language support via localization data in code
- Why: No external dependency on ICU or translation APIs; works offline and in resource-constrained environments
- Consequence: Larger binary footprint and manual translation maintenance; language updates require code changes
-
TimePeriod as ordered pair (start, end) with interval relationships
- Why: Simple model for temporal reasoning; covers most business logic (overlap, containment,
- Consequence: undefined
πͺ€Traps & gotchas
Region context (timezone + calendar + locale triplet) is core to API but requires understanding when parsing ambiguous datesβdefaults may not match user expectation. TimeZone DST transitions and Calendar differences (Gregorian vs Islamic, week numbering) can produce surprising results if not explicitly specified. Colloquial formatter relies on embedded language strings (140+ languages)βadding new languages requires code changes, not external data files. No visible environment variable requirements or external service dependencies.
ποΈArchitecture
π‘Concepts to learn
- Calendar-aware date arithmetic β Adding '1 month' varies by calendar type (Gregorian, Islamic, Hebrew); SwiftDate abstracts this so 1.month respects the active Calendar, not just 30 days
- Region context (timezone + calendar + locale) β A date has no meaning without context; SwiftDate's Region type bundles TimeZone, Calendar, and Locale to prevent silent bugs from mismatched contexts
- Colloquial/relative date formatting β Converting absolute dates to human text ('2 hours ago', 'next week') requires language-specific rules (plural forms, gendered nouns); SwiftDate bundles 140+ language datasets
- ISO8601 and RFC standards compliance β Auto-parsing of 15+ formats (ISO8601, RFC5322, RSS) requires regex patterns and strict validation; critical for interop with web APIs and feeds
- Time period operations and relations β Scheduling logic needs overlap detection, merging, and enumeration of date ranges; SwiftDate's TimePeriod types handle overlaps/containment/gaps
- Daylight Saving Time (DST) edge cases β Adding time across DST boundaries (e.g., +25 hours near clock-backward spring) produces non-obvious results; SwiftDate must respect TimeZone rules
- Codable serialization of temporal data β Encoding dates to JSON requires choosing a format (ISO8601, Unix timestamp, custom); SwiftDate's Codable support handles polymorphic formats
πRelated repos
apple/swift-foundationβ Upstream Calendar/TimeZone/DateFormatter implementations that SwiftDate extendsevermeer/EVReflectionβ Companion library by same ecosystem; handles Codable reflection patterns used in SwiftDate's serializationnicklockwood/DateToolsβ Direct alternative: Objective-C/Swift date toolkit; lacks timezone-aware math and 140+ language support but older/simpler APIjfsso/JSQDataKitβ Complementary utility for Core Data + date querying; often paired with SwiftDate in iOS projects needing persistent date storagevapor/vaporβ Popular Swift server framework listed in README; SwiftDate is the de facto date library for Vapor backends
πͺPR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for DateInRegion timezone edge cases
The repo has extensive DateInRegion functionality (Sources/SwiftDate/DateInRegion/) but no visible test file structure in the provided listing. Timezone handling is notoriously tricky with daylight saving time transitions, leap seconds, and region-specific rules. A new contributor could add targeted tests for DST transitions, timezone offset changes, and region-specific date math operations to prevent regressions.
- [ ] Create Tests/SwiftDate/DateInRegion/DateInRegionTimezoneTests.swift
- [ ] Add test cases for DST transitions (spring forward, fall back) using Region.swift
- [ ] Add test cases for date math across timezone boundaries (e.g., adding hours during DST change)
- [ ] Add test cases for region-specific calendar rules (e.g., week start day differences)
- [ ] Run against Linux target to ensure cross-platform consistency
Add GitHub Actions CI workflow for multi-platform Swift testing
The repo shows .travis.yml (outdated CI) but no GitHub Actions workflow files. Given SwiftDate supports 'all Apple platforms and even on Linux and Swift Server Side frameworks', a modern workflow should test against iOS, macOS, Linux, and Swift Package Manager. This ensures compatibility claims are actually validated on every PR.
- [ ] Create .github/workflows/swift-tests.yml with matrix for iOS, macOS, watchOS, tvOS, Linux
- [ ] Add Swift Package Manager build step (swift build, swift test)
- [ ] Add SwiftLint validation step using .swiftlint.yml config already in repo
- [ ] Add code coverage reporting for Sources/SwiftDate/
- [ ] Test against multiple Swift versions (5.3+) to catch compatibility issues
Expand ISOFormatter and ISOParser test coverage with RFC3339 and custom ISO variants
Sources/SwiftDate/Formatters/ISOFormatter.swift and ISOParser.swift handle critical parsing logic but no dedicated test file is visible. ISO8601 has many variants (RFC3339, basic format, extended format, week dates). Adding comprehensive tests prevents silent parsing failures and documents expected behavior for edge cases like fractional seconds and timezone variations.
- [ ] Create Tests/SwiftDate/Formatters/ISOParserTests.swift with RFC3339 compliance tests
- [ ] Add test cases for: basic format (20230115), extended format (2023-01-15), week dates (2023-W03-5)
- [ ] Add test cases for timezone variants: Z, +00:00, +0000, missing timezone
- [ ] Add test cases for fractional seconds: .1, .123, .123456789
- [ ] Add test cases for invalid ISO strings to verify error handling
- [ ] Cross-reference with String+Parser.swift to ensure consistency
πΏGood first issues
- Add unit tests for timezone edge cases in Date+Compare.swift (DST transitions, leap seconds, year boundaries) since 90% coverage suggests 10% is untestedβlikely in boundary conditions.
- Enhance Documentation/7.Format_UnicodeTable.md with interactive examples showing all 140+ supported language outputs for colloquial formatter, using the Playground infrastructure.
- Implement missing TimeInterval conversion methodsβDocumentation/6.TimeInterval_Formatting.md exists but Sources/ structure doesn't show a dedicated TimeInterval+Extensions.swift; add conversions like toMonths(), toYears() handling calendar variance.
βTop contributors
Click to expand
Top contributors
- @malcommac β 71 commits
- @RomanPodymov β 8 commits
- @lammertw β 2 commits
- @sammygutierrez β 2 commits
- @msmollin β 1 commits
πRecent commits
Click to expand
Recent commits
5d94322β Bump 7.0.0 (malcommac)4dc40e7β Cleanup of return for single line statements (malcommac)d981727β Replacing RelativeFormatter (malcommac)264b5e5β Removed RelativeFormatter class (malcommac)6190d0cβ Merge branch 'release/6.3.1' (malcommac)22857e6β Merge branch 'master' into develop (malcommac)ecf0ebaβ Bump to 6.3.1. podspec (malcommac)4d7499bβ fix #763: set minimum deployment target to iOS 9 and tvOS 9 for Carthage (malcommac)7de89abβ Update README.md (malcommac)d0c0b0bβ Update README.md (malcommac)
πSecurity observations
The SwiftDate codebase demonstrates generally good security posture as a pure date/time manipulation library. No critical vulnerabilities were identified in the file structure. The primary security concerns are typical of open-source Swift projects: ensuring CI/CD configuration properly handles secrets, SwiftLint rules enforce secure coding practices, and dependencies are properly managed and version-controlled. Since this is a utility library focused on date operations, it has minimal attack surface (no network calls, no database operations, no user input sanitization needs in typical use). Recommendations focus on configuration hygiene and dependency management best practices.
- Low Β· Missing FUNDING.yml Configuration Review β
.github/FUNDING.yml. The .github/FUNDING.yml file is present but its contents were not provided for analysis. This file can potentially contain sponsorship links or external references that should be reviewed to ensure they point to legitimate, verified sources. Fix: Review the FUNDING.yml file to ensure all links are legitimate and from official sources. Verify that no malicious sponsorship URLs have been injected. - Low Β· SwiftLint Configuration Not Analyzed β
.swiftlint.yml. The .swiftlint.yml configuration file exists but its contents were not provided. SwiftLint security rules should be properly configured to catch potential code quality and security issues. Fix: Ensure SwiftLint configuration includes security-focused rules such as disabling force unwrapping, checking for force casts, and validating error handling patterns. - Low Β· Travis CI Configuration Present β
.travis.yml. The .travis.yml file indicates use of Travis CI for continuous integration. Without seeing the file contents, it's unclear if sensitive credentials or environment variables are properly managed. Fix: Ensure all sensitive credentials in CI/CD pipelines use encrypted environment variables. Never commit secrets to version control. Use repository-level secret management. - Low Β· Package.swift Dependency Management β
Package.swift. The Package.swift file (Swift Package Manager configuration) was referenced but its contents were not provided. Dependency versions should be pinned or version constraints specified to prevent supply chain attacks. Fix: Review Package.swift to ensure all dependencies use version pinning or specific version ranges. Regularly audit dependencies for known vulnerabilities using tools likeswift package show-dependencies.
LLM-derived; treat as a starting point, not a security audit.
πWhere to read next
- Open issues β current backlog
- Recent PRs β what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals β see the live page for receipts. Re-run on a new commit to refresh.