quando/README.md
Oliver Jakoubek f748b0e134 feat(quando-91w): initialize project structure and tooling
- Initialize go.mod with module path code.beautifulmachines.dev/quando
- Set Go version to 1.22+ (using 1.25.6)
- Create directory structure (internal/calc/, .github/workflows/)
- Add comprehensive README.md with project overview, features, and examples
- Add MIT LICENSE
- Populate .gitignore for Go projects
- Create GitHub Actions CI workflow for testing, linting, and benchmarking

All acceptance criteria met:
✓ go.mod initialized with correct module path
✓ Go 1.22+ specified in go.mod
✓ Directory structure created
✓ README.md with project overview
✓ LICENSE file (MIT)
✓ .gitignore for Go projects
✓ Basic CI/CD workflow
2026-02-11 16:28:14 +01:00

155 lines
4.1 KiB
Markdown

# quando
> Intuitive and idiomatic date calculations for Go
**quando** is a standalone Go library for complex date operations that are cumbersome or impossible with the Go standard library alone. It provides a fluent API for date arithmetic, parsing, formatting, and timezone-aware calculations.
## Features
- **Fluent API**: Chain operations naturally: `quando.Now().Add(2, Months).StartOf(Week)`
- **Month-End Aware**: Handles edge cases like `Jan 31 + 1 month = Feb 28`
- **DST Safe**: Calendar-based arithmetic (not clock-based)
- **Zero Dependencies**: Only Go stdlib
- **Immutable**: Thread-safe by design
- **i18n Ready**: Multilingual formatting (EN, DE in Phase 1)
- **Testable**: Built-in Clock abstraction for deterministic tests
## Installation
```bash
go get code.beautifulmachines.dev/quando
```
## Quick Start
```go
import "code.beautifulmachines.dev/quando"
// Get current date
now := quando.Now()
// Date arithmetic with month-end handling
date := quando.From(time.Date(2026, 1, 31, 0, 0, 0, 0, time.UTC))
result := date.Add(1, quando.Months) // Feb 28, 2026 (not overflow)
// Snap to boundaries
monday := quando.Now().StartOf(quando.Week) // This week's Monday 00:00
endOfMonth := quando.Now().EndOf(quando.Month) // Last day of month 23:59:59
// Next/Previous dates
nextFriday := quando.Now().Next(time.Friday)
prevMonday := quando.Now().Prev(time.Monday)
// Differences
duration := quando.Diff(startDate, endDate)
months := duration.Months()
humanReadable := duration.Human() // "2 years, 3 months, 5 days"
// Parsing (automatic format detection)
date, err := quando.Parse("2026-02-09")
date, err := quando.Parse("09.02.2026") // EU format
date, err := quando.Parse("3 days ago") // Relative
// Formatting
date.Format(quando.ISO) // "2026-02-09"
date.Format(quando.Long) // "February 9, 2026"
date.FormatLayout("02 Jan") // "09 Feb"
// Timezone conversion
utc := date.InTimezone("UTC")
berlin := date.InTimezone("Europe/Berlin")
// Date inspection
week := date.WeekNumber() // ISO 8601 week number
quarter := date.Quarter() // 1-4
dayOfYear := date.DayOfYear() // 1-366
```
## Core Concepts
### Month-End Overflow Handling
When adding months, if the target day doesn't exist, quando snaps to the last valid day:
```go
jan31 := quando.From(time.Date(2026, 1, 31, 0, 0, 0, 0, time.UTC))
feb28 := jan31.Add(1, quando.Months) // Feb 28, not March 3
```
### DST-Aware Arithmetic
Adding days means "same time on next calendar day", not "24 hours later":
```go
// During DST transition (23-hour day)
date := quando.From(time.Date(2026, 3, 31, 2, 0, 0, 0, cetLocation))
next := date.Add(1, quando.Days) // April 1, 2:00 CEST (not 3:00)
```
### Immutability
All operations return new instances. Original values are never modified:
```go
original := quando.Now()
modified := original.Add(1, quando.Days)
// original is unchanged
```
## Testing
quando provides a `Clock` interface for deterministic tests:
```go
// In production
date := quando.Now()
// In tests
fixedTime := time.Date(2026, 2, 9, 12, 0, 0, 0, time.UTC)
clock := quando.NewFixedClock(fixedTime)
date := clock.Now() // Always returns Feb 9, 2026
```
## Requirements
- Go 1.22 or later
- No external dependencies
## Documentation
Full documentation available at: [pkg.go.dev/code.beautifulmachines.dev/quando](https://pkg.go.dev/code.beautifulmachines.dev/quando)
## License
MIT License - see [LICENSE](LICENSE) file for details.
## Contributing
Contributions welcome! Please ensure:
- Tests pass (`go test ./...`)
- Code is formatted (`go fmt ./...`)
- No vet warnings (`go vet ./...`)
- Coverage ≥95% for new code
## Roadmap
### Phase 1 (Current)
- ✅ Project setup
- 🚧 Core date operations
- 🚧 Parsing and formatting
- 🚧 Timezone handling
- 🚧 i18n (EN, DE)
### Phase 2
- Date ranges and series
- Batch operations
- Performance optimizations
### Phase 3
- Holiday calendars
- Business day calculations
- Extended language support
## Acknowledgments
Inspired by [Moment.js](https://momentjs.com/), [Carbon](https://carbon.nesbot.com/), and [date-fns](https://date-fns.org/), but designed to be idiomatic Go.