feat(quando-41g): implement timezone conversion with DST support
Add In() method to Date type for converting between IANA timezones. Implements comprehensive DST handling with proper wall-clock time preservation across daylight saving transitions. Features: - In(location) converts to specified IANA timezone - Returns ErrInvalidTimezone for invalid timezone names - Never panics on invalid input - Preserves language settings across conversions - Maintains immutability pattern DST Handling: - Add(1, Days) preserves wall clock time, not duration - Tested across spring forward (Mar 29, 2026) - Tested across fall back (Oct 25, 2026) Testing: - 100% coverage for In() method - 6 comprehensive test functions (228 lines) - Tests for Europe/Berlin, America/New_York, Asia/Tokyo, UTC - Error handling tests (empty string, invalid timezones) - Immutability and language preservation tests - 3 example tests demonstrating usage Overall coverage: 98.1%
This commit is contained in:
parent
065b767b54
commit
57f9f689d9
4 changed files with 319 additions and 4 deletions
39
date.go
39
date.go
|
|
@ -1,6 +1,7 @@
|
|||
package quando
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -101,6 +102,44 @@ func (d Date) WithLang(lang Lang) Date {
|
|||
}
|
||||
}
|
||||
|
||||
// In converts the date to the specified IANA timezone.
|
||||
// Returns error for invalid timezone names. Never panics.
|
||||
//
|
||||
// The method uses the IANA Timezone Database (e.g., "America/New_York", "Europe/Berlin", "UTC").
|
||||
// Daylight Saving Time (DST) transitions are handled automatically by the timezone database.
|
||||
//
|
||||
// When combined with arithmetic operations, DST-safe behavior is preserved:
|
||||
// Add(1, Days) means "same wall clock time on next calendar day", not "24 hours later".
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// utc := quando.From(time.Date(2026, 6, 15, 12, 0, 0, 0, time.UTC))
|
||||
// berlin, err := utc.In("Europe/Berlin")
|
||||
// // berlin is 2026-06-15 14:00:00 CEST (UTC+2 in summer)
|
||||
//
|
||||
// For a list of valid timezone names, see: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
func (d Date) In(location string) (Date, error) {
|
||||
// Validate input
|
||||
if location == "" {
|
||||
return Date{}, fmt.Errorf("timezone location is empty: %w", ErrInvalidTimezone)
|
||||
}
|
||||
|
||||
// Load timezone from IANA database
|
||||
loc, err := time.LoadLocation(location)
|
||||
if err != nil {
|
||||
return Date{}, fmt.Errorf("loading timezone %q: %w", location, ErrInvalidTimezone)
|
||||
}
|
||||
|
||||
// Convert time to new timezone
|
||||
converted := d.t.In(loc)
|
||||
|
||||
// Return new Date with converted time, preserving language
|
||||
return Date{
|
||||
t: converted,
|
||||
lang: d.lang,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// String returns the ISO 8601 representation of the date (YYYY-MM-DD HH:MM:SS).
|
||||
// This method is called automatically by fmt.Println and similar functions.
|
||||
func (d Date) String() string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue