goda

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 16, 2025 License: MIT Imports: 12 Imported by: 0

README

goda

English | 中文

CI Go Reference Go Report Card codecov

ThreeTen/JSR-310 model in Go

A Go implementation inspired by Java's java.time package (JSR-310), providing immutable date and time types that are type-safe and easy to use.

Features

Core Types
  • 📅 LocalDate: Date without time (e.g., 2024-03-15)
  • LocalTime: Time without date (e.g., 14:30:45.123456789)
  • 📆 LocalDateTime: Date-time without timezone (e.g., 2024-03-15T14:30:45.123456789)
  • 🌐 ZoneOffset: Time-zone offset from Greenwich/UTC (e.g., +08:00, -05:00, Z)
  • 🌍 OffsetDateTime: Date-time with offset (e.g., 2024-03-15T14:30:45.123456789+01:00)
  • 🔢 Field: Enumeration of date-time fields (like Java's ChronoField)
  • 🔍 TemporalAccessor: Universal interface for querying temporal objects
  • 📊 TemporalValue: Type-safe wrapper for field values with validation state
Key Features
  • ISO 8601 basic format support (yyyy-MM-dd, HH:mm:ss[.nnnnnnnnn], combined with 'T')
  • Java.time compatible formatting: Fractional seconds aligned to 3-digit boundaries (milliseconds, microseconds, nanoseconds)
  • Full JSON and SQL database integration
  • Date arithmetic: Add/subtract days, months, years with overflow handling
  • Type-safe field access: Query any field with TemporalValue return type that validates support and overflow
  • TemporalAccessor interface: Universal query pattern across all temporal types
  • Chain operations: Fluent API with error handling for complex mutations
  • Immutable: All operations return new values
  • Type-safe: Compile-time safety with distinct types
  • Zero-value friendly: Zero values are properly handled

Installation

go get github.com/iseki0/goda

Quick Start

Basic Usage
package main

import (
    "fmt"
    "github.com/iseki0/goda"
)

func main() {
    // Create dates and times
    date := goda.MustLocalDateOf(2024, goda.March, 15)
    time := goda.MustLocalTimeOf(14, 30, 45, 123456789)
    datetime := date.AtTime(time)  // or time.AtDate(date)
    
    fmt.Println(date)     // 2024-03-15
    fmt.Println(time)     // 14:30:45.123456789
    fmt.Println(datetime) // 2024-03-15T14:30:45.123456789
    
    // Create from components directly
    datetime2 := goda.MustLocalDateTimeOf(2024, goda.March, 15, 14, 30, 45, 123456789)
    
    // With time zone offset
    offset := goda.MustZoneOffsetOfHours(1)  // +01:00
    offsetDateTime := datetime.AtOffset(offset)
    fmt.Println(offsetDateTime) // 2024-03-15T14:30:45.123456789+01:00
    
    // Parse from strings
    date, _ = goda.LocalDateParse("2024-03-15")
    time = goda.MustLocalTimeParse("14:30:45.123456789")
    datetime = goda.MustLocalDateTimeParse("2024-03-15T14:30:45")
    
    // Get current date/time
    today := goda.LocalDateNow()
    now := goda.LocalTimeNow()
    currentDateTime := goda.LocalDateTimeNow()
    currentOffsetDateTime := goda.OffsetDateTimeNow()
    
    // Date arithmetic
    tomorrow := today.Chain().PlusDays(1).MustGet()
    nextMonth := today.Chain().PlusMonths(1).MustGet()
    nextYear := today.Chain().PlusYears(1).MustGet()
    
    // Comparisons
    if tomorrow.IsAfter(today) {
        fmt.Println("Tomorrow is after today!")
    }
}
Field Access with TemporalValue

Access individual date-time fields using the Field enumeration with type-safe TemporalValue returns:

date := goda.MustLocalDateOf(2024, goda.March, 15)

// Check field support
fmt.Println(date.IsSupportedField(goda.FieldDayOfMonth))  // true
fmt.Println(date.IsSupportedField(goda.FieldHourOfDay))   // false

// Get field values with validation
year := date.GetField(goda.FieldYear)
if year.Valid() {
    fmt.Println("Year:", year.Int64())  // 2024
}

dayOfWeek := date.GetField(goda.FieldDayOfWeek)
if dayOfWeek.Valid() {
    fmt.Println("Day of week:", dayOfWeek.Int())  // 5 (Friday)
}

// Unsupported fields return unsupported TemporalValue
hourOfDay := date.GetField(goda.FieldHourOfDay)
if hourOfDay.Unsupported() {
    fmt.Println("Hour field is not supported for LocalDate")
}

// Time fields
time := goda.MustLocalTimeOf(14, 30, 45, 123456789)
hour := time.GetField(goda.FieldHourOfDay)
if hour.Valid() {
    fmt.Println("Hour:", hour.Int())  // 14
}

nanoOfDay := time.GetField(goda.FieldNanoOfDay)
if nanoOfDay.Valid() {
    fmt.Println("Nanoseconds since midnight:", nanoOfDay.Int64())
}

TemporalValue API:

  • Valid() bool: Returns true if the field is supported and no overflow occurred
  • Unsupported() bool: Returns true if the field is not supported by this temporal type
  • Overflow() bool: Returns true if the field value overflowed (reserved for future use)
  • Int64() int64: Get the raw value as int64
  • Int() int: Get the value as int (for convenience)

Why TemporalValue?

The TemporalValue return type provides type-safe field queries that prevent silent errors:

  • Explicit validation: Check Valid() before using the value
  • Clear error semantics: Distinguish between unsupported fields and actual errors
  • Future-proof: Ready for overflow detection when needed
  • No silent zeros: Unlike raw int64 returns, you can distinguish between "0" and "unsupported"
TemporalAccessor Interface

All temporal types implement the TemporalAccessor interface, providing a uniform query pattern:

// TemporalAccessor provides read-only access to temporal fields
type TemporalAccessor interface {
    IsZero() bool
    IsSupportedField(field Field) bool
    GetField(field Field) TemporalValue
}

// Write generic functions that work with any temporal type
func printYear(t goda.TemporalAccessor) {
    if year := t.GetField(goda.FieldYear); year.Valid() {
        fmt.Printf("Year: %d\n", year.Int())
    }
}

// Works with LocalDate, LocalTime, or LocalDateTime
printYear(goda.LocalDateNow())
printYear(goda.LocalDateTimeNow())
Chain Operations

All temporal types support chain operations for fluent, error-handled mutations. Chain operations allow you to perform multiple modifications in a single expression with proper error handling:

// Chain multiple operations fluently
dt := goda.MustLocalDateTimeOf(2024, goda.March, 15, 14, 30, 45, 123456789)

// Chain date and time modifications
meetingTime := dt.Chain().
    PlusDays(7).              // Next week
    WithHour(16).             // At 4 PM
    WithMinute(0).            // On the hour
    WithSecond(0).            // No seconds
    WithNano(0).              // No nanoseconds
    MustGet()                 // Get result (panics on error)

fmt.Println("Meeting scheduled for:", meetingTime)

// Error handling with chains
result, err := dt.Chain().
    PlusMonths(1).
    WithDayOfMonth(32).       // Invalid day - will cause error
    GetResult()               // Returns (zero value, error)

if err != nil {
    fmt.Println("Invalid operation:", err)
    // Use fallback
    validTime := dt.Chain().
        PlusMonths(1).
        WithDayOfMonth(31).   // Valid day
        GetOrElse(dt)         // Fallback to original if error
}
JSON Serialization
type Event struct {
    Name        string                `json:"name"`
    Date        goda.LocalDate        `json:"date"`
    Time        goda.LocalTime        `json:"time"`
    CreatedAt   goda.LocalDateTime    `json:"created_at"`
    ScheduledAt goda.OffsetDateTime   `json:"scheduled_at"`  // With timezone
}

event := Event{
    Name:        "Meeting",
    Date:        goda.MustLocalDateOf(2024, goda.March, 15),
    Time:        goda.MustLocalTimeOf(14, 30, 0, 0),
    CreatedAt:   goda.MustLocalDateTimeParse("2024-03-15T14:30:00"),
    ScheduledAt: goda.MustOffsetDateTimeParse("2024-03-15T14:30:00+08:00"),
}

jsonData, _ := json.Marshal(event)
// {"name":"Meeting","date":"2024-03-15","time":"14:30:00",
//  "created_at":"2024-03-15T14:30:00","scheduled_at":"2024-03-15T14:30:00+08:00"}
Database Integration
type Record struct {
    ID          int64
    CreatedAt   goda.LocalDateTime
    Date        goda.LocalDate
    UpdatedAt   goda.OffsetDateTime  // With timezone for audit trails
}

// Works with database/sql - implements sql.Scanner and driver.Valuer
db.QueryRow("SELECT id, created_at, date, updated_at FROM records WHERE id = ?", 1).Scan(
    &record.ID, &record.CreatedAt, &record.Date, &record.UpdatedAt,
)

// Insert with offset datetime
offset := goda.MustZoneOffsetOfHours(8)
now := goda.OffsetDateTimeNow()
db.Exec("INSERT INTO records (created_at, updated_at) VALUES (?, ?)",
    goda.LocalDateTimeNow(), now)

API Overview

Core Types
Type Description Example
LocalDate Date without time 2024-03-15
LocalTime Time without date 14:30:45.123456789
LocalDateTime Date-time without timezone 2024-03-15T14:30:45
ZoneOffset Time-zone offset from Greenwich/UTC +08:00, -05:00, Z
OffsetDateTime Date-time with offset from UTC 2024-03-15T14:30:45+08:00
Month Month of year (1-12) March
Year Year 2024
DayOfWeek Day of week (1=Monday, 7=Sunday) Friday
Field Date-time field enumeration HourOfDay, DayOfMonth
TemporalAccessor Interface for querying temporal objects Implemented by all temporal types
TemporalValue Type-safe field value with validation Returned by GetField()
Error Structured error with context Provides detailed error information
LocalDateChain Chain operations for LocalDate date.Chain().PlusDays(1).MustGet()
LocalTimeChain Chain operations for LocalTime time.Chain().PlusHours(1).MustGet()
LocalDateTimeChain Chain operations for LocalDateTime dt.Chain().PlusDays(1).MustGet()
OffsetDateTimeChain Chain operations for OffsetDateTime odt.Chain().PlusHours(1).MustGet()
Format Specification

This package uses ISO 8601 basic calendar date and time formats (not the full specification):

LocalDate: yyyy-MM-dd (e.g., "2024-03-15")
Only Gregorian calendar dates. No week dates (YYYY-Www-D) or ordinal dates (YYYY-DDD).

LocalTime: HH:mm:ss[.nnnnnnnnn] (e.g., "14:30:45.123456789")
24-hour format. Fractional seconds up to nanoseconds. Fractional seconds are aligned to 3-digit boundaries (milliseconds, microseconds, nanoseconds) for Java.time compatibility: 100ms → "14:30:45.100", 123.4ms → "14:30:45.123400". Parsing accepts any length of fractional seconds (e.g., "14:30:45.1" → 100ms).

LocalDateTime: yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn] (e.g., "2024-03-15T14:30:45.123456789")
Combined with 'T' separator (lowercase 't' accepted when parsing).

ZoneOffset: ±HH:mm[:ss] or Z for UTC (e.g., "+08:00", "-05:30", "Z")
Hours must be in range [-18, 18], minutes and seconds in [0, 59]. Compact formats (±HH, ±HHMM, ±HHMMSS) are also supported.

OffsetDateTime: yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn]±HH:mm[:ss] (e.g., "2024-03-15T14:30:45+08:00")
Combines LocalDateTime and ZoneOffset. 'Z' is accepted as UTC offset.

Time Formatting

Time values use ISO 8601 format with Java.time compatible fractional second alignment:

Precision Digits Example
Whole seconds 0 14:30:45
Milliseconds 3 14:30:45.100, 14:30:45.123
Microseconds 6 14:30:45.123400, 14:30:45.123456
Nanoseconds 9 14:30:45.000000001, 14:30:45.123456789

Fractional seconds are automatically aligned to 3-digit boundaries (milliseconds, microseconds, nanoseconds), matching Java's LocalTime behavior. Parsing accepts any length of fractional seconds.

Field Constants (30 fields)

Time Fields: NanoOfSecond, NanoOfDay, MicroOfSecond, MicroOfDay, MilliOfSecond, MilliOfDay, SecondOfMinute, SecondOfDay, MinuteOfHour, MinuteOfDay, HourOfAmPm, ClockHourOfAmPm, HourOfDay, ClockHourOfDay, AmPmOfDay

Date Fields: DayOfWeekField, DayOfMonth, DayOfYear, EpochDay, AlignedDayOfWeekInMonth, AlignedDayOfWeekInYear, AlignedWeekOfMonth, AlignedWeekOfYear, MonthOfYear, ProlepticMonth, YearOfEra, YearField, Era

Other Fields: InstantSeconds, OffsetSeconds

Implemented Interfaces

All temporal types (LocalDate, LocalTime, LocalDateTime, OffsetDateTime) implement:

  • TemporalAccessor: Universal query interface with GetField(field Field) TemporalValue
  • fmt.Stringer
  • encoding.TextMarshaler / encoding.TextUnmarshaler
  • encoding.TextAppender
  • json.Marshaler / json.Unmarshaler
  • sql.Scanner / driver.Valuer

Design Philosophy

This package follows the ThreeTen/JSR-310 model (Java's java.time package), providing date and time types that are:

  • Immutable: All operations return new values
  • Type-safe: Distinct types for date, time, and datetime
  • Simple formats: Uses ISO 8601 basic formats (not the full complex specification)
  • Database-friendly: Direct SQL integration
  • Field-based access: Universal field access pattern via TemporalAccessor interface
  • Safe field queries: TemporalValue return type validates field support and prevents silent errors
  • Zero-value safe: Zero values are properly handled throughout
When to Use Each Type

LocalDate, LocalTime, LocalDateTime - Use when timezone is not relevant:

  • Birthdays: "March 15" means March 15 everywhere
  • Business hours: "9:00 AM - 5:00 PM" in local context
  • Schedules: "Meeting at 2:30 PM" without timezone concerns
  • Calendar dates: Historical dates, recurring events

OffsetDateTime - Use when you need a fixed offset from UTC:

  • API timestamps: REST APIs often use RFC3339 with offsets
  • Audit logs: Record exact moment with original timezone offset
  • Event scheduling: When timezone offset matters but DST transitions don't
  • International coordination: "The meeting is at 14:00 UTC+1"

ZoneOffset - Use to represent timezone offsets:

  • Fixed offsets: +08:00, -05:00, Z (UTC)
  • No DST handling: Use when you don't need daylight saving time rules
  • Simple offset arithmetic: Convert between different offsets

For full timezone support with DST transitions, use ZonedDateTime (coming soon).

Documentation

Full API documentation is available at pkg.go.dev.

Contributing

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

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Overview

Package goda provides date and time types following the ThreeTen/JSR-310 model (java.time package).

This package implements the following main types:

  • LocalDate: A date without time (e.g., 2024-03-15)
  • LocalTime: A time without date (e.g., 14:30:45.123456789)
  • LocalDateTime: A date-time without timezone (e.g., 2024-03-15T14:30:45.123456789)
  • ZoneOffset: A time-zone offset from UTC (e.g., +08:00, -05:00, Z)
  • OffsetDateTime: A date-time with offset from UTC (e.g., 2024-03-15T14:30:45+08:00)
  • Year, Month, DayOfWeek: Supporting types for date/time operations

All types implement standard interfaces for serialization:

  • encoding.TextMarshaler and encoding.TextUnmarshaler (ISO 8601 basic format)
  • encoding.json.Marshaler and encoding.json.Unmarshaler
  • database/sql.Scanner and database/sql/driver.Valuer

Note: This package uses ISO 8601 basic formats only (yyyy-MM-dd, HH:mm:ss[.nnnnnnnnn]), not the full complex ISO 8601 specification (no week dates, ordinal dates, or timezone offsets).

Quick Start

See the Example function for comprehensive usage examples.

Design Philosophy

This package follows the ThreeTen/JSR-310 design:

  • Immutable: All operations return new instances
  • Type-safe: Strong typing prevents mixing dates and times
  • Zero-value safe: Zero values are clearly invalid and IsZero() returns true

Comparison with time.Time

Go's time.Time combines date, time, and location. This package separates concerns:

  • Use LocalDate when you only need a date (e.g., birthdays, deadlines)
  • Use LocalTime when you only need a time (e.g., office hours, schedules)
  • Convert to/from time.Time when timezone information is needed

Format Specification

This package uses ISO 8601 basic calendar date and time formats (not the full specification):

  • LocalDate: yyyy-MM-dd (e.g., "2024-03-15") Only Gregorian calendar dates. No week dates (YYYY-Www-D) or ordinal dates (YYYY-DDD).

  • LocalTime: HH:mm:ss[.nnnnnnnnn] (e.g., "14:30:45.123456789") 24-hour format. Fractional seconds up to nanoseconds. Fractional seconds are aligned to 3-digit boundaries (milliseconds, microseconds, nanoseconds) for Java.time compatibility: 100ms → "14:30:45.100", 123.4ms → "14:30:45.123400". Parsing accepts any length of fractional seconds (e.g., "14:30:45.1" → 100ms).

  • LocalDateTime: yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn] (e.g., "2024-03-15T14:30:45.123456789") Combined with 'T' separator (lowercase 't' accepted when parsing).

  • ZoneOffset: ±HH:mm[:ss] or Z for UTC (e.g., "+08:00", "-05:30", "Z") Hours must be in range [-18, 18], minutes and seconds in [0, 59]. Compact formats (±HH, ±HHMM, ±HHMMSS) are also supported.

  • OffsetDateTime: yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn]±HH:mm[:ss] (e.g., "2024-03-15T14:30:45+08:00") Combines LocalDateTime and ZoneOffset. 'Z' is accepted as UTC offset.

Example

Example demonstrates basic usage of the goda package.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Create a specific date
	date := goda.MustLocalDateOf(2024, goda.March, 15)
	fmt.Println("LocalDate:", date)

	// Create a specific time
	timeOfDay := goda.MustLocalTimeOf(14, 30, 45, 0)
	fmt.Println("LocalTime:", timeOfDay)

	// Combine date and time
	datetime := date.AtTime(timeOfDay)
	fmt.Println("LocalDateTime:", datetime)

	// With timezone offset
	offset := goda.MustZoneOffsetOfHours(8) // +08:00
	offsetDateTime := datetime.AtOffset(offset)
	fmt.Println("OffsetDateTime:", offsetDateTime)

	// Parse from string
	parsedDate := goda.MustLocalDateParse("2024-03-15")
	parsedTime := goda.MustLocalTimeParse("14:30:45.123456789")
	parsedDateTime := goda.MustLocalDateTimeParse("2024-03-15T14:30:45.123456789")
	parsedOffsetDateTime := goda.MustOffsetDateTimeParse("2024-03-15T14:30:45+08:00")

	fmt.Println("Parsed LocalDate:", parsedDate)
	fmt.Println("Parsed LocalTime:", parsedTime)
	fmt.Println("Parsed LocalDateTime:", parsedDateTime)
	fmt.Println("Parsed OffsetDateTime:", parsedOffsetDateTime)

	// LocalDate arithmetic
	tomorrow := date.Chain().PlusDays(1).MustGet()
	nextMonth := date.Chain().PlusMonths(1).MustGet()
	nextYear := date.Chain().PlusYears(1).MustGet()

	fmt.Println("Tomorrow:", tomorrow)
	fmt.Println("Next month:", nextMonth)
	fmt.Println("Next year:", nextYear)

	// Comparisons
	date1 := goda.MustLocalDateOf(2024, goda.March, 15)
	date2 := goda.MustLocalDateOf(2024, goda.March, 20)
	if date1.IsBefore(date2) {
		fmt.Println("date1 is before date2")
	}

	// Serialization
	jsonBytes, _ := json.Marshal(date)
	fmt.Println("JSON:", string(jsonBytes))

	str := date.String()
	fmt.Println("String:", str)

}
Output:

LocalDate: 2024-03-15
LocalTime: 14:30:45
LocalDateTime: 2024-03-15T14:30:45
OffsetDateTime: 2024-03-15T14:30:45+08:00
Parsed LocalDate: 2024-03-15
Parsed LocalTime: 14:30:45.123456789
Parsed LocalDateTime: 2024-03-15T14:30:45.123456789
Parsed OffsetDateTime: 2024-03-15T14:30:45+08:00
Tomorrow: 2024-03-16
Next month: 2024-04-15
Next year: 2025-03-15
date1 is before date2
JSON: "2024-03-15"
String: 2024-03-15

Index

Examples

Constants

View Source
const YearMax = 1<<47 - 1
View Source
const YearMin = -YearMax - 1

Variables

This section is empty.

Functions

This section is empty.

Types

type Chain added in v1.0.0

type Chain[T interface{ IsZero() bool }] struct {
	// contains filtered or unexported fields
}

func (Chain[T]) GetError added in v1.0.0

func (c Chain[T]) GetError() error

func (Chain[T]) GetOrElse added in v1.0.0

func (c Chain[T]) GetOrElse(other T) T

func (Chain[T]) GetOrElseGet added in v1.0.0

func (c Chain[T]) GetOrElseGet(other func() T) T

func (Chain[T]) GetResult added in v1.0.0

func (c Chain[T]) GetResult() (T, error)

func (Chain[T]) IsZero added in v1.0.0

func (c Chain[T]) IsZero() bool

func (Chain[T]) MustGet added in v1.0.0

func (c Chain[T]) MustGet() T

type DayOfWeek

type DayOfWeek int

DayOfWeek represents a day-of-week in the ISO-8601 calendar system, where Monday=1 and Sunday=7. This differs from time.Weekday where Sunday=0.

const (
	Monday    DayOfWeek = iota + 1 // Monday (day 1)
	Tuesday                        // Tuesday (day 2)
	Wednesday                      // Wednesday (day 3)
	Thursday                       // Thursday (day 4)
	Friday                         // Friday (day 5)
	Saturday                       // Saturday (day 6)
	Sunday                         // Sunday (day 7)
)

Days of the week constants.

func DayOfWeekFromGoWeekday

func DayOfWeekFromGoWeekday(w time.Weekday) DayOfWeek

DayOfWeekFromGoWeekday converts a time.Weekday to DayOfWeek.

func (DayOfWeek) GoWeekday

func (d DayOfWeek) GoWeekday() time.Weekday

GoWeekday converts this day-of-week to time.Weekday. Note that DayOfWeek uses ISO-8601 (Monday=1, Sunday=7) while time.Weekday uses Sunday=0, Monday=1, etc.

func (DayOfWeek) IsZero

func (d DayOfWeek) IsZero() bool

IsZero returns true if this is the zero value (not a valid day-of-week).

func (DayOfWeek) String

func (d DayOfWeek) String() string

String returns the English name of the day (e.g., "Monday", "Sunday"). Returns empty string for zero value.

type Error

type Error struct {
	// contains filtered or unexported fields
}

Error is the error type used by this package. It wraps error messages with the "goda: " prefix.

func (Error) Error

func (e Error) Error() string

Error implements the error interface.

func (Error) Unwrap added in v1.0.0

func (e Error) Unwrap() error

type Field added in v0.0.3

type Field int

Field represents a date-time field, such as month-of-year or hour-of-day. This is similar to Java's ChronoField.

const (
	// FieldNanoOfSecond represents the nano-of-second field (0-999,999,999).
	FieldNanoOfSecond Field = iota + 1

	// FieldNanoOfDay represents the nano-of-day field (0-86,399,999,999,999).
	FieldNanoOfDay

	// FieldMicroOfSecond represents the micro-of-second field (0-999,999).
	FieldMicroOfSecond

	// FieldMicroOfDay represents the micro-of-day field (0-86,399,999,999).
	FieldMicroOfDay

	// FieldMilliOfSecond represents the milli-of-second field (0-999).
	FieldMilliOfSecond

	// FieldMilliOfDay represents the milli-of-day field (0-86,399,999).
	FieldMilliOfDay

	// FieldSecondOfMinute represents the second-of-minute field (0-59).
	FieldSecondOfMinute

	// FieldSecondOfDay represents the second-of-day field (0-86,399).
	FieldSecondOfDay

	// FieldMinuteOfHour represents the minute-of-hour field (0-59).
	FieldMinuteOfHour

	// FieldMinuteOfDay represents the minute-of-day field (0-1,439).
	FieldMinuteOfDay

	// FieldHourOfAmPm represents the hour-of-am-pm field (0-11).
	FieldHourOfAmPm

	// FieldClockHourOfAmPm represents the clock-hour-of-am-pm field (1-12).
	FieldClockHourOfAmPm

	// FieldHourOfDay represents the hour-of-day field (0-23).
	FieldHourOfDay

	// FieldClockHourOfDay represents the clock-hour-of-day field (1-24).
	FieldClockHourOfDay

	// FieldAmPmOfDay represents the am-pm-of-day field (0=AM, 1=PM).
	FieldAmPmOfDay

	// FieldDayOfWeek represents the day-of-week field (1=Monday, 7=Sunday).
	FieldDayOfWeek

	// FieldAlignedDayOfWeekInMonth represents the aligned day-of-week within a month.
	FieldAlignedDayOfWeekInMonth

	// FieldAlignedDayOfWeekInYear represents the aligned day-of-week within a year.
	FieldAlignedDayOfWeekInYear

	// FieldDayOfMonth represents the day-of-month field (1-31).
	FieldDayOfMonth

	// FieldDayOfYear represents the day-of-year field (1-366).
	FieldDayOfYear

	// FieldEpochDay represents the epoch-day field, based on the Unix epoch of 1970-01-01.
	FieldEpochDay

	// FieldAlignedWeekOfMonth represents the aligned week within a month.
	FieldAlignedWeekOfMonth

	// FieldAlignedWeekOfYear represents the aligned week within a year.
	FieldAlignedWeekOfYear

	// FieldMonthOfYear represents the month-of-year field (1=January, 12=December).
	FieldMonthOfYear

	// FieldProlepticMonth represents the proleptic-month, counting months sequentially from year 0.
	FieldProlepticMonth

	// FieldYearOfEra represents the year within the era.
	FieldYearOfEra

	// FieldYear represents the proleptic year, such as 2024.
	FieldYear

	// FieldEra represents the era field.
	FieldEra

	// FieldInstantSeconds represents the instant epoch-seconds.
	FieldInstantSeconds

	// FieldOffsetSeconds represents the offset from UTC/Greenwich in seconds.
	FieldOffsetSeconds
)

Field constants representing date and time components.

func (Field) IsDateBased added in v0.0.8

func (f Field) IsDateBased() bool

IsDateBased checks if this field represents a component of a date.

A field is date-based if it can be derived from FieldEpochDay. Note that it is valid for both IsDateBased() and IsTimeBased() to return false, such as when representing a field like minute-of-week.

Returns true if this field is a component of a date.

func (Field) IsTimeBased added in v0.0.8

func (f Field) IsTimeBased() bool

IsTimeBased checks if this field represents a component of a time.

A field is time-based if it can be derived from FieldNanoOfDay. Note that it is valid for both IsDateBased() and IsTimeBased() to return false, such as when representing a field like minute-of-week.

Returns true if this field is a component of a time.

func (Field) JavaName added in v0.0.9

func (f Field) JavaName() string

func (Field) String added in v0.0.3

func (f Field) String() string

String returns the name of the field.

func (Field) Valid added in v1.0.0

func (f Field) Valid() bool

type LocalDate

type LocalDate struct {
	// contains filtered or unexported fields
}

LocalDate represents a date without a time zone in the Gregorian calendar system, such as 2024-03-15. It stores the year, month, and day-of-month.

LocalDate is comparable and can be used as a map key. The zero value represents an unset date and IsZero returns true for it.

LocalDate implements sql.Scanner and driver.Valuer for database operations, encoding.TextMarshaler and encoding.TextUnmarshaler for text serialization, and json.Marshaler and json.Unmarshaler for JSON serialization.

Format: yyyy-MM-dd (e.g., "2024-03-15"). Uses ISO 8601 basic calendar date format. Week dates (YYYY-Www-D) and ordinal dates (YYYY-DDD) are not supported.

func LocalDateMax added in v1.0.0

func LocalDateMax() LocalDate

func LocalDateMin added in v1.0.0

func LocalDateMin() LocalDate

func LocalDateNow added in v0.0.2

func LocalDateNow() LocalDate

LocalDateNow returns the current date in the system's local time zone. This is equivalent to LocalDateOfGoTime(time.Now()). For UTC time, use LocalDateNowUTC. For a specific timezone, use LocalDateNowIn.

Example

ExampleLocalDateNow demonstrates how to get the current date.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Get current date in local timezone
	today := goda.LocalDateNow()

	// check that we got a valid date
	fmt.Printf("Got valid date: %v\n", !today.IsZero())
	fmt.Printf("Has year component: %v\n", today.Year() != 0)

}
Output:

Got valid date: true
Has year component: true

func LocalDateNowIn added in v0.0.2

func LocalDateNowIn(loc *time.Location) LocalDate

LocalDateNowIn returns the current date in the specified time zone. This is equivalent to LocalDateOfGoTime(time.Now().In(loc)).

Example

ExampleLocalDateNowIn demonstrates how to get the current date in a specific timezone.

package main

import (
	"fmt"
	"time"

	"github.com/iseki0/goda"
)

func main() {
	// Get current date in Tokyo timezone
	tokyo, _ := time.LoadLocation("Asia/Tokyo")
	todayTokyo := goda.LocalDateNowIn(tokyo)

	// Verify it's valid
	fmt.Printf("Valid: %v\n", !todayTokyo.IsZero())

}
Output:

Valid: true

func LocalDateNowUTC added in v0.0.2

func LocalDateNowUTC() LocalDate

LocalDateNowUTC returns the current date in UTC. This is equivalent to LocalDateOfGoTime(time.Now().UTC()).

Example

ExampleLocalDateNowUTC demonstrates how to get the current date in UTC.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Get current date in UTC
	todayUTC := goda.LocalDateNowUTC()

	// Verify it's a valid date
	fmt.Printf("Valid: %v\n", !todayUTC.IsZero())

}
Output:

Valid: true

func LocalDateOf added in v1.0.0

func LocalDateOf(year Year, month Month, dayOfMonth int) (d LocalDate, e error)

LocalDateOf creates a new LocalDate from the specified year, month, and day-of-month. Returns an error if the date is invalid (e.g., month out of range 1-12, day out of range for the month, or February 29 in a non-leap year).

Example

ExampleNewLocalDate demonstrates how to create a date.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Create a valid date
	date, err := goda.LocalDateOf(2024, goda.January, 15)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(date)

	// Try to create an invalid date
	_, err = goda.LocalDateOf(2024, goda.February, 30)
	fmt.Println("Error:", err)

}
Output:

2024-01-15
Error: goda: invalid date February 30

func LocalDateOfEpochDays added in v1.0.0

func LocalDateOfEpochDays(days int64) (LocalDate, error)

LocalDateOfEpochDays creates a LocalDate from the number of days since Unix epoch (1970-01-01). Positive values represent dates after the epoch, negative before.

func LocalDateOfGoTime added in v0.0.11

func LocalDateOfGoTime(t time.Time) LocalDate

LocalDateOfGoTime creates a LocalDate from a time.Time. The time zone and time-of-day components are ignored. Returns zero value if t.IsZero().

Example

ExampleLocalDateOfGoTime demonstrates converting from time.Time to LocalDate.

package main

import (
	"fmt"
	"time"

	"github.com/iseki0/goda"
)

func main() {
	// Convert from time.LocalTime
	goTime := time.Date(2024, time.March, 15, 14, 30, 0, 0, time.UTC)
	date := goda.LocalDateOfGoTime(goTime)
	fmt.Println(date)

}
Output:

2024-03-15

func LocalDateOfYearDay added in v1.0.0

func LocalDateOfYearDay(year Year, dayOfYear int) (r LocalDate, e error)

func LocalDateParse added in v1.0.0

func LocalDateParse(s string) (LocalDate, error)

LocalDateParse parses a date string in yyyy-MM-dd format. Returns an error if the string is invalid or represents an invalid date.

Supported format: yyyy-MM-dd (e.g., "2024-03-15") Week dates and ordinal dates are not supported.

Example:

date, err := LocalDateParse("2024-03-15")
if err != nil {
    // handle error
}
Example

ExampleLocalDateParse demonstrates parsing a date from a string.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Parse a date string
	date, err := goda.LocalDateParse("2024-03-15")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(date)

}
Output:

2024-03-15

func MustLocalDateOf added in v1.0.0

func MustLocalDateOf(year Year, month Month, dayOfMonth int) LocalDate

MustLocalDateOf creates a new LocalDate from the specified year, month, and day-of-month. Panics if the date is invalid. Use LocalDateOf for error handling.

Example

ExampleMustNewLocalDate demonstrates how to create a date that panics on error.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Create a date (panics if invalid)
	date := goda.MustLocalDateOf(2024, goda.March, 15)
	fmt.Println(date)

}
Output:

2024-03-15

func MustLocalDateOfUnixEpochDays added in v1.0.0

func MustLocalDateOfUnixEpochDays(days int64) LocalDate

func MustLocalDateParse added in v1.0.0

func MustLocalDateParse(s string) LocalDate

MustLocalDateParse parses a date string in yyyy-MM-dd format. Panics if the string is invalid. Use LocalDateParse for error handling.

Example:

date := MustLocalDateParse("2024-03-15")
Example

ExampleMustLocalDateParse demonstrates parsing a date that panics on error.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Parse a date string (panics if invalid)
	date := goda.MustLocalDateParse("2024-03-15")
	fmt.Println(date)

}
Output:

2024-03-15

func (LocalDate) AppendText

func (d LocalDate) AppendText(b []byte) ([]byte, error)

AppendText implements the encoding.TextAppender interface. It appends the date in yyyy-MM-dd format to b and returns the extended buffer.

func (LocalDate) AtTime added in v0.0.6

func (d LocalDate) AtTime(time LocalTime) LocalDateTime

AtTime combines this date with a time to create a LocalDateTime.

Example

ExampleLocalDate_AtTime demonstrates creating a datetime from date and time.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.March, 15)
	time := goda.MustLocalTimeOf(14, 30, 45, 123456789)
	dt := date.AtTime(time)
	fmt.Println(dt)

}
Output:

2024-03-15T14:30:45.123456789

func (LocalDate) Chain added in v1.0.0

func (d LocalDate) Chain() (chain LocalDateChain)

func (LocalDate) Compare

func (d LocalDate) Compare(other LocalDate) int

Compare compares this date with another date. Returns -1 if this date is before other, 0 if equal, and 1 if after. Zero values are considered less than non-zero values.

Example

ExampleLocalDate_Compare demonstrates comparing dates.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date1 := goda.MustLocalDateOf(2024, goda.March, 15)
	date2 := goda.MustLocalDateOf(2024, goda.March, 20)
	date3 := goda.MustLocalDateOf(2024, goda.March, 15)

	fmt.Println("date1 < date2:", date1.IsBefore(date2))
	fmt.Println("date1 > date2:", date1.IsAfter(date2))
	fmt.Println("date1 == date3:", date1.Compare(date3) == 0)

}
Output:

date1 < date2: true
date1 > date2: false
date1 == date3: true

func (LocalDate) DayOfMonth

func (d LocalDate) DayOfMonth() int

DayOfMonth returns the day-of-month component of this date (1-31).

func (LocalDate) DayOfWeek

func (d LocalDate) DayOfWeek() DayOfWeek

DayOfWeek returns the day-of-week for this date. Returns 0 for zero value, otherwise Monday=1 through Sunday=7.

Example

ExampleLocalDate_DayOfWeek demonstrates getting the day of week.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.March, 15)
	fmt.Println("Day of week:", date.DayOfWeek())
	fmt.Println("Is Friday?", date.DayOfWeek() == goda.Friday)

}
Output:

Day of week: Friday
Is Friday? true

func (LocalDate) DayOfYear

func (d LocalDate) DayOfYear() int

DayOfYear returns the day-of-year for this date (1-366). Returns 0 for zero value.

func (LocalDate) GetField added in v0.0.8

func (d LocalDate) GetField(field Field) TemporalValue

GetField returns the value of the specified field as a TemporalValue. This method queries the date for the value of the specified field. The returned value may be unsupported if the field is not supported by LocalDate.

If the date is zero (IsZero() returns true), an unsupported TemporalValue is returned. For fields not supported by LocalDate (such as time fields), an unsupported TemporalValue is returned.

Supported fields include:

  • FieldDayOfWeek: returns the day of week (1=Monday, 7=Sunday)
  • FieldDayOfMonth: returns the day of month (1-31)
  • FieldDayOfYear: returns the day of year (1-366)
  • FieldMonthOfYear: returns the month (1=January, 12=December)
  • FieldYear: returns the proleptic year
  • FieldYearOfEra: returns the year within the era (same as FieldYear for CE dates)
  • FieldEra: returns the era (0=BCE, 1=CE)
  • FieldEpochDay: returns the number of days since Unix epoch (1970-01-01)
  • FieldProlepticMonth: returns the number of months since year 0

Overflow Analysis: None of the supported fields can overflow int64 in practice:

  • FieldDayOfWeek: range 1-7, cannot overflow
  • FieldDayOfMonth: range 1-31, cannot overflow
  • FieldDayOfYear: range 1-366, cannot overflow
  • FieldMonthOfYear: range 1-12, cannot overflow
  • FieldYear/FieldYearOfEra: Year is int64, direct cast, cannot overflow
  • FieldEra: values 0 or 1, cannot overflow
  • FieldEpochDay: int64, calculated from year/month/day which are bounded by LocalDate's internal representation
  • FieldProlepticMonth: Year * 12 + Month. Year is int64, so max value is approximately int64_max * 12, which would overflow. However, LocalDate stores Year in the upper 48 bits of a 64-bit value, limiting the practical range to approximately ±140 trillion years, making overflow impossible in any realistic scenario.
Example

ExampleLocalDate_GetField demonstrates querying date fields with TemporalValue.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.March, 15) // Friday

	// Query various date fields
	dayOfWeek := date.GetField(goda.FieldDayOfWeek)
	if dayOfWeek.Valid() {
		fmt.Printf("Day of week: %d (1=Monday, 7=Sunday)\n", dayOfWeek.Int())
	}

	month := date.GetField(goda.FieldMonthOfYear)
	if month.Valid() {
		fmt.Printf("Month: %d\n", month.Int())
	}

	year := date.GetField(goda.FieldYear)
	if year.Valid() {
		fmt.Printf("Year: %d\n", year.Int())
	}

	// Query unsupported field (time field on date)
	hour := date.GetField(goda.FieldHourOfDay)
	if hour.Unsupported() {
		fmt.Println("Hour field is not supported for LocalDate")
	}

}
Output:

Day of week: 5 (1=Monday, 7=Sunday)
Month: 3
Year: 2024
Hour field is not supported for LocalDate
Example (AdvancedFields)

ExampleLocalDate_GetField_advancedFields demonstrates advanced date field queries.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.March, 15)

	// Day of year (1-366)
	dayOfYear := date.GetField(goda.FieldDayOfYear)
	fmt.Printf("Day of year: %d\n", dayOfYear.Int())

	// Epoch days (days since 1970-01-01)
	epochDay := date.GetField(goda.FieldEpochDay)
	fmt.Printf("Days since Unix epoch: %d\n", epochDay.Int64())

	// Proleptic month (months since year 0)
	prolepticMonth := date.GetField(goda.FieldProlepticMonth)
	fmt.Printf("Proleptic month: %d\n", prolepticMonth.Int64())

	// FieldEra (0=BCE, 1=CE)
	era := date.GetField(goda.FieldEra)
	if era.Int() == 1 {
		fmt.Println("FieldEra: CE (Common FieldEra)")
	}

}
Output:

Day of year: 75
Days since Unix epoch: 19797
Proleptic month: 24290
FieldEra: CE (Common FieldEra)

func (LocalDate) GoTime

func (d LocalDate) GoTime() time.Time

GoTime converts this date to a time.Time at midnight UTC. Returns time.Time{} (zero) for zero value.

func (LocalDate) IsAfter

func (d LocalDate) IsAfter(other LocalDate) bool

IsAfter returns true if this date is after the specified date.

func (LocalDate) IsBefore

func (d LocalDate) IsBefore(other LocalDate) bool

IsBefore returns true if this date is before the specified date.

func (LocalDate) IsLeapYear

func (d LocalDate) IsLeapYear() bool

IsLeapYear returns true if the year of this date is a leap year. A leap year is divisible by 4, unless it's divisible by 100 (but not 400).

func (LocalDate) IsSupportedField added in v0.0.3

func (d LocalDate) IsSupportedField(field Field) bool

IsSupportedField returns true if the field is supported by LocalDate.

func (LocalDate) IsZero

func (d LocalDate) IsZero() bool

IsZero returns true if this is the zero value of LocalDate.

func (LocalDate) LengthOfMonth added in v1.0.0

func (d LocalDate) LengthOfMonth() int

LengthOfMonth returns the number of days in the month of this date. Returns 28, 29, 30, or 31 depending on the month and whether it's a leap year. Returns 0 for zero value.

Example

ExampleLocalDate_LengthOfMonth demonstrates getting the month length.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// February in leap year
	date1 := goda.MustLocalDateOf(2024, goda.February, 15)
	fmt.Printf("February 2024: %d days\n", date1.LengthOfMonth())

	// February in non-leap year
	date2 := goda.MustLocalDateOf(2023, goda.February, 15)
	fmt.Printf("February 2023: %d days\n", date2.LengthOfMonth())

	// April (30-day month)
	date3 := goda.MustLocalDateOf(2024, goda.April, 15)
	fmt.Printf("April 2024: %d days\n", date3.LengthOfMonth())

	// March (31-day month)
	date4 := goda.MustLocalDateOf(2024, goda.March, 15)
	fmt.Printf("March 2024: %d days\n", date4.LengthOfMonth())

}
Output:

February 2024: 29 days
February 2023: 28 days
April 2024: 30 days
March 2024: 31 days

func (LocalDate) LengthOfYear added in v1.0.0

func (d LocalDate) LengthOfYear() int

LengthOfYear returns the number of days in the year of this date. Returns 365 for non-leap years and 366 for leap years. Returns 0 for zero value.

Example

ExampleLocalDate_LengthOfYear demonstrates getting the year length.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Leap year
	date1 := goda.MustLocalDateOf(2024, goda.March, 15)
	fmt.Printf("Year 2024: %d days\n", date1.LengthOfYear())

	// Non-leap year
	date2 := goda.MustLocalDateOf(2023, goda.March, 15)
	fmt.Printf("Year 2023: %d days\n", date2.LengthOfYear())

	// Century year divisible by 400 (leap year)
	date3 := goda.MustLocalDateOf(2000, goda.June, 15)
	fmt.Printf("Year 2000: %d days\n", date3.LengthOfYear())

	// Century year not divisible by 400 (non-leap year)
	date4 := goda.MustLocalDateOf(1900, goda.June, 15)
	fmt.Printf("Year 1900: %d days\n", date4.LengthOfYear())

}
Output:

Year 2024: 366 days
Year 2023: 365 days
Year 2000: 366 days
Year 1900: 365 days

func (LocalDate) MarshalJSON

func (d LocalDate) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface. It returns the date as a JSON string in yyyy-MM-dd format, or empty string for zero value.

Example

ExampleLocalDate_MarshalJSON demonstrates JSON serialization.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.March, 15)
	jsonBytes, _ := json.Marshal(date)
	fmt.Println(string(jsonBytes))

}
Output:

"2024-03-15"

func (LocalDate) MarshalText

func (d LocalDate) MarshalText() (text []byte, err error)

MarshalText implements the encoding.TextMarshaler interface. It returns the date in yyyy-MM-dd format, or empty for zero value.

func (LocalDate) Month

func (d LocalDate) Month() Month

Month returns the month component of this date (1-12).

func (*LocalDate) Scan

func (d *LocalDate) Scan(src any) error

Scan implements the sql.Scanner interface. It supports scanning from nil, string, []byte, and time.Time. Nil values are converted to the zero value of LocalDate.

func (LocalDate) String

func (d LocalDate) String() string

String returns the date in yyyy-MM-dd format, or empty string for zero value.

func (LocalDate) UnixEpochDays

func (d LocalDate) UnixEpochDays() int64

UnixEpochDays returns the number of days since Unix epoch (1970-01-01). Positive values represent dates after the epoch, negative before. Returns 0 for zero value.

func (*LocalDate) UnmarshalJSON

func (d *LocalDate) UnmarshalJSON(bytes []byte) error

UnmarshalJSON implements the json.Unmarshaler interface. It accepts JSON strings in yyyy-MM-dd format or JSON null.

Example

ExampleLocalDate_UnmarshalJSON demonstrates JSON deserialization.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	var date goda.LocalDate
	jsonData := []byte(`"2024-03-15"`)
	err := json.Unmarshal(jsonData, &date)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(date)

}
Output:

2024-03-15

func (*LocalDate) UnmarshalText

func (d *LocalDate) UnmarshalText(text []byte) (e error)

UnmarshalText implements the encoding.TextUnmarshaler interface. It parses dates in yyyy-MM-dd format. Empty input is treated as zero value.

func (LocalDate) Value

func (d LocalDate) Value() (driver.Value, error)

Value implements the driver.Valuer interface. It returns nil for zero values, otherwise returns the date as a string in yyyy-MM-dd format.

func (LocalDate) Year

func (d LocalDate) Year() Year

Year returns the year component of this date.

func (LocalDate) YearMonth added in v1.0.0

func (d LocalDate) YearMonth() YearMonth

type LocalDateChain added in v1.0.0

type LocalDateChain struct {
	Chain[LocalDate]
}

func (LocalDateChain) MinusDays added in v1.0.0

func (l LocalDateChain) MinusDays(days int64) LocalDateChain

func (LocalDateChain) MinusMonths added in v1.0.0

func (l LocalDateChain) MinusMonths(months int64) LocalDateChain

func (LocalDateChain) MinusWeeks added in v1.0.0

func (l LocalDateChain) MinusWeeks(weeks int64) LocalDateChain
Example

ExampleLocalDateChain_MinusWeeks demonstrates subtracting weeks from a date.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.February, 15)
	fmt.Println("Original:", date)
	fmt.Println("Minus 2 weeks:", date.Chain().MinusWeeks(2).MustGet())

}
Output:

Original: 2024-02-15
Minus 2 weeks: 2024-02-01

func (LocalDateChain) MinusYears added in v1.0.0

func (l LocalDateChain) MinusYears(years int64) LocalDateChain

func (LocalDateChain) PlusDays added in v1.0.0

func (l LocalDateChain) PlusDays(days int64) LocalDateChain
Example

ExampleLocalDateChain_PlusDays demonstrates adding days to a date.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.January, 15)
	fmt.Println("Original:", date)
	fmt.Println("Plus 10 days:", date.Chain().PlusDays(10).MustGet())
	fmt.Println("Minus 10 days:", date.Chain().PlusDays(-10).MustGet())

}
Output:

Original: 2024-01-15
Plus 10 days: 2024-01-25
Minus 10 days: 2024-01-05

func (LocalDateChain) PlusMonths added in v1.0.0

func (l LocalDateChain) PlusMonths(months int64) LocalDateChain
Example

ExampleLocalDateChain_PlusMonths demonstrates adding months to a date.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.January, 31)
	fmt.Println("Original:", date)
	fmt.Println("Plus 1 month:", date.Chain().PlusMonths(1).MustGet())
	fmt.Println("Plus 2 months:", date.Chain().PlusMonths(2).MustGet())

}
Output:

Original: 2024-01-31
Plus 1 month: 2024-02-29
Plus 2 months: 2024-03-31

func (LocalDateChain) PlusWeeks added in v1.0.0

func (l LocalDateChain) PlusWeeks(weeks int64) LocalDateChain
Example

ExampleLocalDate_PlusWeeks demonstrates adding weeks to a date.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.January, 15)
	fmt.Println("Original:", date)
	fmt.Println("Plus 2 weeks:", date.Chain().PlusWeeks(2).MustGet())
	fmt.Println("Minus 1 week:", date.Chain().PlusWeeks(-1).MustGet())

}
Output:

Original: 2024-01-15
Plus 2 weeks: 2024-01-29
Minus 1 week: 2024-01-08

func (LocalDateChain) PlusYears added in v1.0.0

func (l LocalDateChain) PlusYears(years int64) LocalDateChain

func (LocalDateChain) WithDayOfMonth added in v1.0.0

func (l LocalDateChain) WithDayOfMonth(dayOfMonth int) LocalDateChain
Example

ExampleLocalDateChain_WithDayOfMonth demonstrates changing the day of month.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.March, 15)

	// Change to the 1st of the month
	date2, err := date.Chain().WithDayOfMonth(1).GetResult()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("First of month:", date2)

	// Change to the last day of the month
	date3, err := date.Chain().WithDayOfMonth(31).GetResult()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Last of month:", date3)

}
Output:

First of month: 2024-03-01
Last of month: 2024-03-31

func (LocalDateChain) WithDayOfYear added in v1.0.0

func (l LocalDateChain) WithDayOfYear(dayOfYear int) LocalDateChain
Example

ExampleLocalDateChain_WithDayOfYear demonstrates changing the day of year.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.March, 15)
	fmt.Println("Original:", date)

	// Change to the 100th day of the year
	date2, err := date.Chain().WithDayOfYear(100).GetResult()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Day 100:", date2)

	// Change to the 1st day of the year
	date3, err := date.Chain().WithDayOfYear(1).GetResult()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Day 1:", date3)

}
Output:

Original: 2024-03-15
Day 100: 2024-04-09
Day 1: 2024-01-01

func (LocalDateChain) WithField added in v1.0.0

func (l LocalDateChain) WithField(field Field, value TemporalValue) LocalDateChain

WithField returns a copy of this LocalDate with the specified field replaced. Zero values return zero immediately.

Supported fields mirror Java's LocalDate#with(TemporalField, long):

  • FieldDayOfMonth: sets the day-of-month while keeping year and month.
  • FieldDayOfYear: sets the day-of-year while keeping year.
  • FieldMonthOfYear: sets the month-of-year while keeping year and day-of-month (adjusted if necessary).
  • FieldYear: sets the year while keeping month and day-of-month (adjusted if necessary).
  • FieldYearOfEra: sets the year within the current era (same as FieldYear for CE dates).
  • FieldEra: switches between BCE/CE eras while preserving year, month, and day.
  • FieldEpochDay: sets the date based on days since Unix epoch (1970-01-01).
  • FieldProlepticMonth: sets the date based on months since year 0.

Fields outside this list return an error. Range violations propagate the validation error.

func (LocalDateChain) WithMonth added in v1.0.0

func (l LocalDateChain) WithMonth(month Month) LocalDateChain
Example

ExampleLocalDateChain_WithMonth demonstrates changing the month.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	date := goda.MustLocalDateOf(2024, goda.January, 31)
	fmt.Println("Original:", date)

	// Change to February (day will be clamped to 29 in leap year)
	date2, err := date.Chain().WithMonth(goda.February).GetResult()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("February:", date2)

	// Change to March (day 31 is valid)
	date3, err := date.Chain().WithMonth(goda.March).GetResult()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("March:", date3)

}
Output:

Original: 2024-01-31
February: 2024-02-29
March: 2024-03-31

func (LocalDateChain) WithYear added in v1.0.0

func (l LocalDateChain) WithYear(year Year) LocalDateChain
Example

ExampleLocalDateChain_WithYear demonstrates changing the year.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Leap year date (Feb 29)
	date := goda.MustLocalDateOf(2024, goda.February, 29)
	fmt.Println("Original (leap year):", date)

	// Change to non-leap year (day will be clamped to 28)
	date2, err := date.Chain().WithYear(2023).GetResult()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Non-leap year:", date2)

	// Change to another leap year (day 29 is valid)
	date3, err := date.Chain().WithYear(2020).GetResult()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Another leap year:", date3)

}
Output:

Original (leap year): 2024-02-29
Non-leap year: 2023-02-28
Another leap year: 2020-02-29

type LocalDateTime added in v0.0.3

type LocalDateTime struct {
	// contains filtered or unexported fields
}

LocalDateTime represents a date-time without a time zone, such as 2024-03-15T14:30:45.123456789. It combines LocalDate and LocalTime.

LocalDateTime is comparable and can be used as a map key. The zero value represents an unset date-time and IsZero returns true for it.

LocalDateTime implements sql.Scanner and driver.Valuer for database operations, encoding.TextMarshaler and encoding.TextUnmarshaler for text serialization, and json.Marshaler and json.Unmarshaler for JSON serialization.

Format: yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn] (e.g., "2024-03-15T14:30:45.123456789"). Combined date and time with 'T' separator. Lowercase 't' is accepted when parsing. Timezone offsets are not supported.

Example

ExampleLocalDateTime demonstrates basic LocalDateTime usage.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Create from components
	dt := goda.MustLocalDateTimeOf(2024, goda.March, 15, 14, 30, 45, 123456789)
	fmt.Println(dt)

	// Access date and time parts
	fmt.Printf("LocalDate: %s\n", dt.LocalDate())
	fmt.Printf("LocalTime: %s\n", dt.LocalTime())

	// Access individual components
	fmt.Printf("Year: %d, Hour: %d\n", dt.Year(), dt.Hour())

}
Output:

2024-03-15T14:30:45.123456789
LocalDate: 2024-03-15
LocalTime: 14:30:45.123456789
Year: 2024, Hour: 14

func LocalDateTimeNow added in v0.0.3

func LocalDateTimeNow() LocalDateTime

LocalDateTimeNow returns the current date-time in the system's local time zone.

Example

ExampleLocalDateTimeNow demonstrates getting the current datetime.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	now := goda.LocalDateTimeNow()

	// Verify it's valid
	fmt.Printf("Valid: %v\n", !now.IsZero())
	fmt.Printf("Has components: %v\n", now.Year() != 0 && now.Hour() >= 0)

}
Output:

Valid: true
Has components: true

func LocalDateTimeNowIn added in v0.0.3

func LocalDateTimeNowIn(loc *time.Location) LocalDateTime

LocalDateTimeNowIn returns the current date-time in the specified time zone.

func LocalDateTimeNowUTC added in v0.0.3

func LocalDateTimeNowUTC() LocalDateTime

LocalDateTimeNowUTC returns the current date-time in UTC.

func LocalDateTimeOf added in v1.0.0

func LocalDateTimeOf(year Year, month Month, day, hour, minute, second, nanosecond int) (LocalDateTime, error)

LocalDateTimeOf creates a new LocalDateTime from individual components. Returns an error if any component is invalid.

func LocalDateTimeOfEpochSecond added in v1.0.0

func LocalDateTimeOfEpochSecond(epochSecond int64, nanoOfSecond int64, offset ZoneOffset) (r LocalDateTime, e error)

func LocalDateTimeOfGoTime added in v0.0.11

func LocalDateTimeOfGoTime(t time.Time) LocalDateTime

LocalDateTimeOfGoTime creates a LocalDateTime from a time.Time. Returns zero value if t.IsZero().

func LocalDateTimeParse added in v1.0.0

func LocalDateTimeParse(s string) (LocalDateTime, error)

LocalDateTimeParse parses a date-time string in RFC3339-compatible format. The date must be in yyyy-MM-dd form, and the time must be in HH:mm:ss or HH:mm:ss[.nnnnnnnnn] form.

The separator between the date and time may be 'T', 't', or a single space.

Examples:

dt, err := LocalDateTimeParse("2024-03-15T14:30:45.123456789")
dt, err := LocalDateTimeParse("2024-03-15 14:30:45")
dt, err := LocalDateTimeParse("2024-03-15t14:30:45")
Example

ExampleLocalDateTimeParse demonstrates parsing a datetime from a string.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	dt, err := goda.LocalDateTimeParse("2024-03-15T14:30:45.123456789")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(dt)

}
Output:

2024-03-15T14:30:45.123456789

func MustLocalDateTimeOf added in v1.0.0

func MustLocalDateTimeOf(year Year, month Month, day, hour, minute, second, nanosecond int) LocalDateTime

MustLocalDateTimeOf creates a new LocalDateTime from individual components. Panics if any component is invalid.

func MustLocalDateTimeParse added in v1.0.0

func MustLocalDateTimeParse(s string) LocalDateTime

MustLocalDateTimeParse parses a date-time string in yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn] format. Panics if the string is invalid.

Example

ExampleMustLocalDateTimeParse demonstrates parsing that panics on error.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	dt := goda.MustLocalDateTimeParse("2024-03-15T14:30:45")
	fmt.Println(dt)

}
Output:

2024-03-15T14:30:45

func (LocalDateTime) AppendText added in v0.0.3

func (dt LocalDateTime) AppendText(b []byte) ([]byte, error)

AppendText implements encoding.TextAppender.

func (LocalDateTime) AtOffset added in v0.0.11

func (dt LocalDateTime) AtOffset(offset ZoneOffset) OffsetDateTime

func (LocalDateTime) Chain added in v1.0.0

func (dt LocalDateTime) Chain() (chain LocalDateTimeChain)

func (LocalDateTime) Compare added in v0.0.3

func (dt LocalDateTime) Compare(other LocalDateTime) int

Compare compares this date-time with another. Returns -1 if this is before other, 0 if equal, 1 if after.

Example

ExampleLocalDateTime_Compare demonstrates comparing datetimes.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	dt1 := goda.MustLocalDateTimeParse("2024-03-15T14:30:45")
	dt2 := goda.MustLocalDateTimeParse("2024-03-15T14:30:45")
	dt3 := goda.MustLocalDateTimeParse("2024-03-15T15:30:45")

	fmt.Printf("dt1 == dt2: %v\n", dt1.Compare(dt2) == 0)
	fmt.Printf("dt1 < dt3: %v\n", dt1.IsBefore(dt3))
	fmt.Printf("dt3 > dt1: %v\n", dt3.IsAfter(dt1))

}
Output:

dt1 == dt2: true
dt1 < dt3: true
dt3 > dt1: true

func (LocalDateTime) DayOfMonth added in v0.0.3

func (dt LocalDateTime) DayOfMonth() int

DayOfMonth returns the day-of-month component.

func (LocalDateTime) DayOfWeek added in v0.0.3

func (dt LocalDateTime) DayOfWeek() DayOfWeek

DayOfWeek returns the day-of-week.

func (LocalDateTime) DayOfYear added in v0.0.3

func (dt LocalDateTime) DayOfYear() int

DayOfYear returns the day-of-year.

func (LocalDateTime) GetField added in v0.0.8

func (dt LocalDateTime) GetField(field Field) TemporalValue

GetField returns the value of the specified field as a TemporalValue. This method queries the date-time for the value of the specified field. The returned value may be unsupported if the field is not supported by LocalDateTime.

If the date-time is zero (IsZero() returns true), an unsupported TemporalValue is returned.

LocalDateTime supports all fields from both LocalDate and LocalTime. For fields that are supported by the underlying LocalDate or LocalTime, this method delegates to the appropriate component.

Supported fields include all date fields (FieldDayOfWeek, FieldDayOfMonth, FieldDayOfYear, FieldMonthOfYear, FieldYear, FieldYearOfEra, FieldEra, FieldEpochDay, FieldProlepticMonth) and all time fields (FieldNanoOfSecond, FieldNanoOfDay, FieldMicroOfSecond, FieldMicroOfDay, FieldMilliOfSecond, FieldMilliOfDay, FieldSecondOfMinute, FieldSecondOfDay, FieldMinuteOfHour, FieldMinuteOfDay, FieldHourOfDay, FieldClockHourOfDay, FieldHourOfAmPm, FieldClockHourOfAmPm, FieldAmPmOfDay).

Overflow Analysis: LocalDateTime delegates to LocalDate and LocalTime, both of which have no overflow issues for their supported fields. Therefore, LocalDateTime.GetField cannot overflow:

  • All date fields are handled by LocalDate.GetField (see LocalDate overflow analysis)
  • All time fields are handled by LocalTime.GetField (see LocalTime overflow analysis)
  • No LocalDateTime-specific fields exist that could cause overflow
Example

ExampleLocalDateTime_GetField demonstrates querying fields from a date-time.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	dt := goda.MustLocalDateTimeOf(2024, goda.March, 15, 14, 30, 45, 123456789)

	// Query date fields
	year := dt.GetField(goda.FieldYear)
	month := dt.GetField(goda.FieldMonthOfYear)
	day := dt.GetField(goda.FieldDayOfMonth)

	if year.Valid() && month.Valid() && day.Valid() {
		fmt.Printf("Date: %04d-%02d-%02d\n", year.Int(), month.Int(), day.Int())
	}

	// Query time fields
	hour := dt.GetField(goda.FieldHourOfDay)
	minute := dt.GetField(goda.FieldMinuteOfHour)
	second := dt.GetField(goda.FieldSecondOfMinute)

	if hour.Valid() && minute.Valid() && second.Valid() {
		fmt.Printf("Time: %02d:%02d:%02d\n", hour.Int(), minute.Int(), second.Int())
	}

	// Query day of week
	dayOfWeek := dt.GetField(goda.FieldDayOfWeek)
	if dayOfWeek.Valid() {
		fmt.Printf("Day of week: %d (Friday)\n", dayOfWeek.Int())
	}

}
Output:

Date: 2024-03-15
Time: 14:30:45
Day of week: 5 (Friday)
Example (Delegation)

ExampleLocalDateTime_GetField_delegation demonstrates field delegation.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	dt := goda.MustLocalDateTimeOf(2024, goda.March, 15, 14, 30, 45, 0)

	// LocalDateTime delegates date fields to LocalDate
	dayOfYear := dt.GetField(goda.FieldDayOfYear)
	fmt.Printf("Day of year: %d\n", dayOfYear.Int())

	// LocalDateTime delegates time fields to LocalTime
	nanoOfDay := dt.GetField(goda.FieldNanoOfDay)
	fmt.Printf("Nanoseconds of day: %d\n", nanoOfDay.Int64())

	// Unsupported fields return unsupported TemporalValue
	offsetSeconds := dt.GetField(goda.FieldOffsetSeconds)
	if offsetSeconds.Unsupported() {
		fmt.Println("FieldOffsetSeconds is not supported for LocalDateTime")
	}

}
Output:

Day of year: 75
Nanoseconds of day: 52245000000000
FieldOffsetSeconds is not supported for LocalDateTime

func (LocalDateTime) GoTime added in v0.0.3

func (dt LocalDateTime) GoTime() time.Time

GoTime converts this date-time to a time.Time in UTC. Returns time.Time{} (zero) for zero value.

func (LocalDateTime) Hour added in v0.0.3

func (dt LocalDateTime) Hour() int

Hour returns the hour component (0-23).

func (LocalDateTime) IsAfter added in v0.0.3

func (dt LocalDateTime) IsAfter(other LocalDateTime) bool

IsAfter returns true if this date-time is after the specified date-time.

func (LocalDateTime) IsBefore added in v0.0.3

func (dt LocalDateTime) IsBefore(other LocalDateTime) bool

IsBefore returns true if this date-time is before the specified date-time.

func (LocalDateTime) IsLeapYear added in v0.0.3

func (dt LocalDateTime) IsLeapYear() bool

IsLeapYear returns true if the year is a leap year.

func (LocalDateTime) IsSupportedField added in v0.0.3

func (dt LocalDateTime) IsSupportedField(field Field) bool

IsSupportedField returns true if the field is supported by LocalDateTime. LocalDateTime supports all fields from both LocalDate and LocalTime.

Example

ExampleLocalDateTime_IsSupportedField demonstrates checking field support.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	dt := goda.MustLocalDateTimeOf(2024, goda.March, 15, 14, 30, 45, 0)

	fmt.Printf("Supports FieldHourOfDay: %v\n", dt.IsSupportedField(goda.FieldHourOfDay))
	fmt.Printf("Supports FieldDayOfMonth: %v\n", dt.IsSupportedField(goda.FieldDayOfMonth))
	fmt.Printf("Supports FieldOffsetSeconds: %v\n", dt.IsSupportedField(goda.FieldOffsetSeconds))

}
Output:

Supports FieldHourOfDay: true
Supports FieldDayOfMonth: true
Supports FieldOffsetSeconds: false

func (LocalDateTime) IsZero added in v0.0.3

func (dt LocalDateTime) IsZero() bool

IsZero returns true if this is the zero value.

func (LocalDateTime) LocalDate added in v0.0.3

func (dt LocalDateTime) LocalDate() LocalDate

LocalDate returns the date part of this date-time.

func (LocalDateTime) LocalTime added in v0.0.3

func (dt LocalDateTime) LocalTime() LocalTime

LocalTime returns the time part of this date-time.

func (LocalDateTime) MarshalJSON added in v0.0.3

func (dt LocalDateTime) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

Example

ExampleLocalDateTime_MarshalJSON demonstrates JSON serialization.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	dt := goda.MustLocalDateTimeParse("2024-03-15T14:30:45.123456789")
	jsonBytes, _ := json.Marshal(dt)
	fmt.Println(string(jsonBytes))

}
Output:

"2024-03-15T14:30:45.123456789"

func (LocalDateTime) MarshalText added in v0.0.3

func (dt LocalDateTime) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler.

func (LocalDateTime) Millisecond added in v0.0.3

func (dt LocalDateTime) Millisecond() int

Millisecond returns the millisecond component (0-999).

func (LocalDateTime) Minute added in v0.0.3

func (dt LocalDateTime) Minute() int

Minute returns the minute component (0-59).

func (LocalDateTime) Month added in v0.0.3

func (dt LocalDateTime) Month() Month

Month returns the month component.

func (LocalDateTime) Nanosecond added in v0.0.3

func (dt LocalDateTime) Nanosecond() int

Nanosecond returns the nanosecond component (0-999999999).

func (*LocalDateTime) Scan added in v0.0.3

func (dt *LocalDateTime) Scan(src any) error

Scan implements sql.Scanner.

func (LocalDateTime) Second added in v0.0.3

func (dt LocalDateTime) Second() int

Second returns the second component (0-59).

func (LocalDateTime) String added in v0.0.3

func (dt LocalDateTime) String() string

String returns the ISO 8601 string representation (yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn]).

func (*LocalDateTime) UnmarshalJSON added in v0.0.3

func (dt *LocalDateTime) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

Example

ExampleLocalDateTime_UnmarshalJSON demonstrates JSON deserialization.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	var dt goda.LocalDateTime
	jsonData := []byte(`"2024-03-15T14:30:45.123456789"`)
	err := json.Unmarshal(jsonData, &dt)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(dt)

}
Output:

2024-03-15T14:30:45.123456789

func (*LocalDateTime) UnmarshalText added in v0.0.3

func (dt *LocalDateTime) UnmarshalText(text []byte) (e error)

UnmarshalText implements encoding.TextUnmarshaler. Accepts ISO 8601 format: yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn]

func (LocalDateTime) Value added in v0.0.3

func (dt LocalDateTime) Value() (driver.Value, error)

Value implements driver.Valuer.

func (LocalDateTime) Year added in v0.0.3

func (dt LocalDateTime) Year() Year

Year returns the year component.

type LocalDateTimeChain added in v1.0.0

type LocalDateTimeChain struct {
	Chain[LocalDateTime]
}

func (LocalDateTimeChain) MinusDays added in v1.0.0

func (l LocalDateTimeChain) MinusDays(days int64) LocalDateTimeChain

func (LocalDateTimeChain) MinusHours added in v1.0.0

func (l LocalDateTimeChain) MinusHours(hours int64) LocalDateTimeChain

func (LocalDateTimeChain) MinusMinutes added in v1.0.0

func (l LocalDateTimeChain) MinusMinutes(minutes int64) LocalDateTimeChain

func (LocalDateTimeChain) MinusMonths added in v1.0.0

func (l LocalDateTimeChain) MinusMonths(months int64) LocalDateTimeChain

func (LocalDateTimeChain) MinusNanos added in v1.0.0

func (l LocalDateTimeChain) MinusNanos(nanos int64) LocalDateTimeChain

func (LocalDateTimeChain) MinusSeconds added in v1.0.0

func (l LocalDateTimeChain) MinusSeconds(seconds int64) LocalDateTimeChain

func (LocalDateTimeChain) MinusWeeks added in v1.0.0

func (l LocalDateTimeChain) MinusWeeks(weeks int64) LocalDateTimeChain

func (LocalDateTimeChain) MinusYears added in v1.0.0

func (l LocalDateTimeChain) MinusYears(years int64) LocalDateTimeChain

func (LocalDateTimeChain) PlusDays added in v1.0.0

func (l LocalDateTimeChain) PlusDays(days int64) LocalDateTimeChain
Example

ExampleLocalDateTimeChain_PlusDays demonstrates adding days.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	dt := goda.MustLocalDateTimeParse("2024-03-15T14:30:45")
	future := dt.Chain().PlusDays(10).MustGet()
	fmt.Println(future)

}
Output:

2024-03-25T14:30:45

func (LocalDateTimeChain) PlusHours added in v1.0.0

func (l LocalDateTimeChain) PlusHours(hours int64) LocalDateTimeChain

func (LocalDateTimeChain) PlusMinutes added in v1.0.0

func (l LocalDateTimeChain) PlusMinutes(minutes int64) LocalDateTimeChain

func (LocalDateTimeChain) PlusMonths added in v1.0.0

func (l LocalDateTimeChain) PlusMonths(months int64) LocalDateTimeChain

func (LocalDateTimeChain) PlusNanos added in v1.0.0

func (l LocalDateTimeChain) PlusNanos(nanos int64) LocalDateTimeChain

func (LocalDateTimeChain) PlusSeconds added in v1.0.0

func (l LocalDateTimeChain) PlusSeconds(seconds int64) LocalDateTimeChain

func (LocalDateTimeChain) PlusWeeks added in v1.0.0

func (l LocalDateTimeChain) PlusWeeks(weeks int64) LocalDateTimeChain

func (LocalDateTimeChain) PlusYears added in v1.0.0

func (l LocalDateTimeChain) PlusYears(years int64) LocalDateTimeChain

func (LocalDateTimeChain) WithDayOfMonth added in v1.0.0

func (l LocalDateTimeChain) WithDayOfMonth(dayOfMonth int) LocalDateTimeChain

func (LocalDateTimeChain) WithDayOfYear added in v1.0.0

func (l LocalDateTimeChain) WithDayOfYear(dayOfYear int) LocalDateTimeChain

func (LocalDateTimeChain) WithField added in v1.0.0

func (l LocalDateTimeChain) WithField(field Field, value TemporalValue) LocalDateTimeChain

func (LocalDateTimeChain) WithHour added in v1.0.0

func (l LocalDateTimeChain) WithHour(hour int) LocalDateTimeChain

func (LocalDateTimeChain) WithMinute added in v1.0.0

func (l LocalDateTimeChain) WithMinute(minute int) LocalDateTimeChain

func (LocalDateTimeChain) WithMonth added in v1.0.0

func (l LocalDateTimeChain) WithMonth(month Month) LocalDateTimeChain

func (LocalDateTimeChain) WithNano added in v1.0.0

func (l LocalDateTimeChain) WithNano(nanoOfSecond int) LocalDateTimeChain

func (LocalDateTimeChain) WithSecond added in v1.0.0

func (l LocalDateTimeChain) WithSecond(second int) LocalDateTimeChain

func (LocalDateTimeChain) WithYear added in v1.0.0

func (l LocalDateTimeChain) WithYear(year Year) LocalDateTimeChain

type LocalTime

type LocalTime struct {
	// contains filtered or unexported fields
}

LocalTime represents a time without a date or time zone, such as 14:30:45.123456789. It stores the hour, minute, second, and nanosecond.

LocalTime is comparable and can be used as a map key. The zero value represents an unset time and IsZero returns true for it. Note: 00:00:00 (midnight) is a valid time and is different from the zero value.

LocalTime implements sql.Scanner and driver.Valuer for database operations, encoding.TextMarshaler and encoding.TextUnmarshaler for text serialization, and json.Marshaler and json.Unmarshaler for JSON serialization.

Format: HH:mm:ss[.nnnnnnnnn] (e.g., "14:30:45.123456789"). Uses 24-hour format. Fractional seconds support nanosecond precision and are aligned to 3-digit boundaries (milliseconds, microseconds, nanoseconds) for Java.time compatibility. Timezone offsets are not supported.

Internally, v uses bit 63 (the highest bit) as a validity flag. If bit 63 is set, the time is valid and bits 0-62 contain nanoseconds since midnight. If bit 63 is clear (v == 0), the time is invalid/zero. Max nanoseconds in a day: 86,399,999,999,999 (< 2^47), so we have plenty of space.

Example (Hour)

ExampleLocalTime_hour demonstrates accessing time components.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	t := goda.MustLocalTimeOf(14, 30, 45, 123456789)
	fmt.Println("Hour:", t.Hour())
	fmt.Println("Minute:", t.Minute())
	fmt.Println("Second:", t.Second())
	fmt.Println("Millisecond:", t.Millisecond())
	fmt.Println("Nano:", t.Nano())

}
Output:

Hour: 14
Minute: 30
Second: 45
Millisecond: 123
Nano: 123456789

func LocalTimeNow added in v0.0.2

func LocalTimeNow() LocalTime

LocalTimeNow returns the current time in the system's local time zone. This is equivalent to LocalTimeOfGoTime(time.Now()). For UTC time, use LocalTimeNowUTC. For a specific timezone, use LocalTimeNowIn.

Example

ExampleLocalTimeNow demonstrates how to get the current time.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Get current time in local timezone
	now := goda.LocalTimeNow()

	// Verify it's valid and within range
	fmt.Printf("Valid: %v\n", !now.IsZero())
	fmt.Printf("Hour in range: %v\n", now.Hour() >= 0 && now.Hour() < 24)

}
Output:

Valid: true
Hour in range: true

func LocalTimeNowIn added in v0.0.2

func LocalTimeNowIn(loc *time.Location) LocalTime

LocalTimeNowIn returns the current time in the specified time zone. This is equivalent to LocalTimeOfGoTime(time.Now().In(loc)).

Example

ExampleLocalTimeNowIn demonstrates how to get the current time in a specific timezone.

package main

import (
	"fmt"
	"time"

	"github.com/iseki0/goda"
)

func main() {
	// Get current time in Tokyo timezone
	tokyo, _ := time.LoadLocation("Asia/Tokyo")
	nowTokyo := goda.LocalTimeNowIn(tokyo)

	// Verify it's valid
	fmt.Printf("Valid: %v\n", !nowTokyo.IsZero())

}
Output:

Valid: true

func LocalTimeNowUTC added in v0.0.2

func LocalTimeNowUTC() LocalTime

LocalTimeNowUTC returns the current time in UTC. This is equivalent to LocalTimeOfGoTime(time.Now().UTC()).

Example

ExampleLocalTimeNowUTC demonstrates how to get the current time in UTC.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Get current time in UTC
	nowUTC := goda.LocalTimeNowUTC()

	// Verify it's valid
	fmt.Printf("Valid: %v\n", !nowUTC.IsZero())

}
Output:

Valid: true

func LocalTimeOf added in v1.0.0

func LocalTimeOf(hour, minute, second, nanosecond int) (r LocalTime, e error)

LocalTimeOf creates a new LocalTime from the specified hour, minute, second, and nanosecond. Returns an error if any component is out of range: - hour must be 0-23 - minute must be 0-59 - second must be 0-59 - nanosecond must be 0-999999999

Example

ExampleLocalTimeOf demonstrates how to create a time.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Create a valid time
	t, err := goda.LocalTimeOf(14, 30, 45, 123456789)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(t)

	// Try to create an invalid time
	_, err = goda.LocalTimeOf(25, 0, 0, 0)
	fmt.Println("Error:", err)

}
Output:

14:30:45.123456789
Error: goda: invalid value of HourOfDay (valid range 0 - 23): 25

func LocalTimeOfGoTime added in v0.0.11

func LocalTimeOfGoTime(t time.Time) LocalTime

LocalTimeOfGoTime creates a LocalTime from a time.Time. The date and time zone components are ignored. Returns zero value if t.IsZero().

Example

ExampleLocalTimeOfGoTime demonstrates converting from time.Time to LocalTime.

package main

import (
	"fmt"
	"time"

	"github.com/iseki0/goda"
)

func main() {
	// Convert from time.LocalTime
	goTime := time.Date(2024, time.March, 15, 14, 30, 45, 123456789, time.UTC)
	t := goda.LocalTimeOfGoTime(goTime)
	fmt.Println(t)

}
Output:

14:30:45.123456789

func LocalTimeOfNanoOfDay added in v0.0.11

func LocalTimeOfNanoOfDay(nanoOfDay int64) (r LocalTime, e error)

LocalTimeOfNanoOfDay creates a LocalTime from the nanosecond-of-day value. Returns an error if nanoOfDay is out of the valid range (0 to 86,399,999,999,999). The valid range represents 00:00:00.000000000 to 23:59:59.999999999.

Example:

// Create time for 12:00:00
lt, err := LocalTimeOfNanoOfDay(12 * 60 * 60 * 1000000000)

func LocalTimeOfSecondOfDay added in v0.0.11

func LocalTimeOfSecondOfDay(secondOfDay int) (r LocalTime, e error)

LocalTimeOfSecondOfDay creates a LocalTime from the second-of-day value. Returns an error if secondOfDay is out of the valid range (0 to 86,399). The valid range represents 00:00:00 to 23:59:59. The nanosecond component will be set to zero.

Example:

// Create time for 12:00:00
lt, err := LocalTimeOfSecondOfDay(12 * 60 * 60)

func LocalTimeParse added in v1.0.0

func LocalTimeParse(s string) (LocalTime, error)

LocalTimeParse parses a time string in HH:mm:ss[.nnnnnnnnn] format (24-hour). Returns an error if the string is invalid or represents an invalid time.

Accepts fractional seconds of any length (1-9 digits):

  • HH:mm:ss (e.g., "14:30:45")
  • HH:mm:ss.f (e.g., "14:30:45.1" → 100 milliseconds)
  • HH:mm:ss.fff (e.g., "14:30:45.123" → 123 milliseconds)
  • HH:mm:ss.ffffff (e.g., "14:30:45.123456" → 123.456 milliseconds)
  • HH:mm:ss.nnnnnnnnn (e.g., "14:30:45.123456789" → full nanosecond precision)

Note: Output formatting aligns to 3-digit boundaries (milliseconds, microseconds, nanoseconds). Timezone offsets are not supported.

Example:

time, err := LocalTimeParse("14:30:45.123")
if err != nil {
    // handle error
}
Example

ExampleLocalTimeParse demonstrates parsing a time from a string.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Parse a time string
	t, err := goda.LocalTimeParse("14:30:45.123456789")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(t)

}
Output:

14:30:45.123456789

func MustLocalTimeOf added in v1.0.0

func MustLocalTimeOf(hour, minute, second, nanosecond int) LocalTime

MustLocalTimeOf creates a new LocalTime from the specified hour, minute, second, and nanosecond. Panics if any component is out of range. Use LocalTimeOf for error handling.

Example

ExampleMustLocalTimeOf demonstrates how to create a time that panics on error.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Create a time (panics if invalid)
	t := goda.MustLocalTimeOf(14, 30, 45, 0)
	fmt.Println(t)

	// Midnight
	midnight := goda.MustLocalTimeOf(0, 0, 0, 0)
	fmt.Println("Midnight:", midnight)

}
Output:

14:30:45
Midnight: 00:00:00

func MustLocalTimeOfNanoOfDay added in v0.0.11

func MustLocalTimeOfNanoOfDay(nanoOfDay int64) LocalTime

MustLocalTimeOfNanoOfDay creates a LocalTime from the nanosecond-of-day value. Panics if nanoOfDay is out of range. Use LocalTimeOfNanoOfDay for error handling.

Example:

// Create time for 12:00:00
lt := MustLocalTimeOfNanoOfDay(12 * 60 * 60 * 1000000000)

func MustLocalTimeOfSecondOfDay added in v0.0.11

func MustLocalTimeOfSecondOfDay(secondOfDay int) LocalTime

MustLocalTimeOfSecondOfDay creates a LocalTime from the second-of-day value. Panics if secondOfDay is out of range. Use LocalTimeOfSecondOfDay for error handling.

Example:

// Create time for 12:00:00
lt := MustLocalTimeOfSecondOfDay(12 * 60 * 60)

func MustLocalTimeParse added in v1.0.0

func MustLocalTimeParse(s string) LocalTime

MustLocalTimeParse parses a time string in HH:mm:ss[.nnnnnnnnn] format (24-hour). Panics if the string is invalid. Use LocalTimeParse for error handling.

Example:

time := MustLocalTimeParse("14:30:45.123456789")
Example

ExampleMustLocalTimeParse demonstrates parsing a time that panics on error.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Parse a time string (panics if invalid)
	t := goda.MustLocalTimeParse("14:30:45")
	fmt.Println(t)

}
Output:

14:30:45

func (LocalTime) AppendText

func (t LocalTime) AppendText(b []byte) ([]byte, error)

AppendText in ISO-8601 format

func (LocalTime) AtDate added in v0.0.6

func (t LocalTime) AtDate(date LocalDate) LocalDateTime

AtDate combines this time with a date to create a LocalDateTime.

Example

ExampleLocalTime_AtDate demonstrates creating a datetime from time and date.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	time := goda.MustLocalTimeOf(14, 30, 45, 123456789)
	date := goda.MustLocalDateOf(2024, goda.March, 15)
	dt := time.AtDate(date)
	fmt.Println(dt)

}
Output:

2024-03-15T14:30:45.123456789

func (LocalTime) Chain added in v1.0.0

func (t LocalTime) Chain() (chain LocalTimeChain)

func (LocalTime) Compare

func (t LocalTime) Compare(other LocalTime) int

Compare compares this time with another time. Returns -1 if this time is before other, 0 if equal, and 1 if after. Zero values are considered less than non-zero values.

Example

ExampleLocalTime_Compare demonstrates comparing times.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	t1 := goda.MustLocalTimeOf(14, 30, 0, 0)
	t2 := goda.MustLocalTimeOf(15, 0, 0, 0)
	t3 := goda.MustLocalTimeOf(14, 30, 0, 0)

	fmt.Println("t1 < t2:", t1.IsBefore(t2))
	fmt.Println("t1 > t2:", t1.IsAfter(t2))
	fmt.Println("t1 == t3:", t1.Compare(t3) == 0)

}
Output:

t1 < t2: true
t1 > t2: false
t1 == t3: true

func (LocalTime) GetField added in v0.0.8

func (t LocalTime) GetField(field Field) TemporalValue

GetField returns the value of the specified field as a TemporalValue. This method queries the time for the value of the specified field. The returned value may be unsupported if the field is not supported by LocalTime.

If the time is zero (IsZero() returns true), an unsupported TemporalValue is returned. For fields not supported by LocalTime (such as date fields), an unsupported TemporalValue is returned.

Supported fields include:

  • FieldNanoOfSecond: returns the nanosecond within the second (0-999,999,999)
  • FieldNanoOfDay: returns the nanosecond of day (0-86,399,999,999,999)
  • FieldMicroOfSecond: returns the microsecond within the second (0-999,999)
  • FieldMicroOfDay: returns the microsecond of day (0-86,399,999,999)
  • FieldMilliOfSecond: returns the millisecond within the second (0-999)
  • FieldMilliOfDay: returns the millisecond of day (0-86,399,999)
  • FieldSecondOfMinute: returns the second within the minute (0-59)
  • FieldSecondOfDay: returns the second of day (0-86,399)
  • FieldMinuteOfHour: returns the minute within the hour (0-59)
  • FieldMinuteOfDay: returns the minute of day (0-1,439)
  • FieldHourOfDay: returns the hour of day (0-23)
  • FieldClockHourOfDay: returns the clock hour of day (1-24)
  • FieldHourOfAmPm: returns the hour within AM/PM (0-11)
  • FieldClockHourOfAmPm: returns the clock hour within AM/PM (1-12)
  • FieldAmPmOfDay: returns AM/PM indicator (0=AM, 1=PM)

Overflow Analysis: None of the supported fields can overflow int64:

  • FieldNanoOfSecond: range 0-999,999,999, cannot overflow
  • FieldNanoOfDay: max 86,399,999,999,999 (< 2^47), cannot overflow
  • FieldMicroOfSecond: range 0-999,999, cannot overflow
  • FieldMicroOfDay: max 86,399,999,999 (< 2^37), cannot overflow
  • FieldMilliOfSecond: range 0-999, cannot overflow
  • FieldMilliOfDay: max 86,399,999 (< 2^27), cannot overflow
  • FieldSecondOfMinute: range 0-59, cannot overflow
  • FieldSecondOfDay: max 86,399 (< 2^17), cannot overflow
  • FieldMinuteOfHour: range 0-59, cannot overflow
  • FieldMinuteOfDay: max 1,439 (< 2^11), cannot overflow
  • FieldHourOfDay: range 0-23, cannot overflow
  • FieldClockHourOfDay: range 1-24, cannot overflow
  • FieldHourOfAmPm: range 0-11, cannot overflow
  • FieldClockHourOfAmPm: range 1-12, cannot overflow
  • FieldAmPmOfDay: values 0 or 1, cannot overflow
Example

ExampleLocalTime_GetField demonstrates querying time fields with TemporalValue.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	t := goda.MustLocalTimeOf(14, 30, 45, 123456789)

	// Query various time fields
	hour := t.GetField(goda.FieldHourOfDay)
	if hour.Valid() {
		fmt.Printf("Hour of day (0-23): %d\n", hour.Int())
	}

	minute := t.GetField(goda.FieldMinuteOfHour)
	if minute.Valid() {
		fmt.Printf("Minute of hour: %d\n", minute.Int())
	}

	second := t.GetField(goda.FieldSecondOfMinute)
	if second.Valid() {
		fmt.Printf("Second of minute: %d\n", second.Int())
	}

	nanos := t.GetField(goda.FieldNanoOfSecond)
	if nanos.Valid() {
		fmt.Printf("Nanoseconds: %d\n", nanos.Int())
	}

	// Query unsupported field (date field on time)
	dayOfMonth := t.GetField(goda.FieldDayOfMonth)
	if dayOfMonth.Unsupported() {
		fmt.Println("FieldDayOfMonth field is not supported for LocalTime")
	}

}
Output:

Hour of day (0-23): 14
Minute of hour: 30
Second of minute: 45
Nanoseconds: 123456789
FieldDayOfMonth field is not supported for LocalTime
Example (ClockHours)

ExampleLocalTime_GetField_clockHours demonstrates 12-hour clock field queries.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Afternoon time (2:30 PM)
	afternoon := goda.MustLocalTimeOf(14, 30, 0, 0)

	// 24-hour format
	hourOfDay := afternoon.GetField(goda.FieldHourOfDay)
	fmt.Printf("24-hour format: %d:30\n", hourOfDay.Int())

	// 12-hour format components
	hourOfAmPm := afternoon.GetField(goda.FieldHourOfAmPm)
	amPm := afternoon.GetField(goda.FieldAmPmOfDay)
	amPmStr := "AM"
	if amPm.Int() == 1 {
		amPmStr = "PM"
	}
	fmt.Printf("12-hour format: %d:30 %s\n", hourOfAmPm.Int(), amPmStr)

	// Clock hour (1-12 instead of 0-11)
	clockHour := afternoon.GetField(goda.FieldClockHourOfAmPm)
	fmt.Printf("Clock hour (1-12): %d:30 %s\n", clockHour.Int(), amPmStr)

	// Midnight special case
	midnight := goda.MustLocalTimeOf(0, 0, 0, 0)
	midnightClock := midnight.GetField(goda.FieldClockHourOfDay)
	fmt.Printf("Midnight clock hour: %d:00\n", midnightClock.Int())

}
Output:

24-hour format: 14:30
12-hour format: 2:30 PM
Clock hour (1-12): 2:30 PM
Midnight clock hour: 24:00
Example (OfDayFields)

ExampleLocalTime_GetField_ofDayFields demonstrates querying cumulative daily values.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	t := goda.MustLocalTimeOf(14, 30, 45, 500000000) // 2:30:45.5 PM

	// Total seconds elapsed since midnight
	secondOfDay := t.GetField(goda.FieldSecondOfDay)
	fmt.Printf("Seconds since midnight: %d\n", secondOfDay.Int())

	// Total minutes elapsed since midnight
	minuteOfDay := t.GetField(goda.FieldMinuteOfDay)
	fmt.Printf("Minutes since midnight: %d\n", minuteOfDay.Int())

	// Total milliseconds elapsed since midnight
	milliOfDay := t.GetField(goda.FieldMilliOfDay)
	fmt.Printf("Milliseconds since midnight: %d\n", milliOfDay.Int64())

	// Total nanoseconds elapsed since midnight
	nanoOfDay := t.GetField(goda.FieldNanoOfDay)
	fmt.Printf("Nanoseconds since midnight: %d\n", nanoOfDay.Int64())

}
Output:

Seconds since midnight: 52245
Minutes since midnight: 870
Milliseconds since midnight: 52245500
Nanoseconds since midnight: 52245500000000

func (LocalTime) GoTime

func (t LocalTime) GoTime() time.Time

GoTime converts this time to a time.Time at the Unix epoch date (1970-01-01) in UTC. Returns time.Time{} (zero) for zero value.

func (LocalTime) Hour

func (t LocalTime) Hour() int

Hour returns the hour component (0-23).

func (LocalTime) IsAfter

func (t LocalTime) IsAfter(other LocalTime) bool

IsAfter returns true if this time is after the specified time.

func (LocalTime) IsBefore

func (t LocalTime) IsBefore(other LocalTime) bool

IsBefore returns true if this time is before the specified time.

func (LocalTime) IsSupportedField added in v0.0.3

func (t LocalTime) IsSupportedField(field Field) bool

IsSupportedField returns true if the field is supported by LocalTime.

func (LocalTime) IsZero

func (t LocalTime) IsZero() bool

IsZero returns true if this is the zero value of LocalTime.

func (LocalTime) MarshalJSON

func (t LocalTime) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

Example

ExampleLocalTime_MarshalJSON demonstrates JSON serialization.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	t := goda.MustLocalTimeOf(14, 30, 45, 123456789)
	jsonBytes, _ := json.Marshal(t)
	fmt.Println(string(jsonBytes))

}
Output:

"14:30:45.123456789"

func (LocalTime) MarshalText

func (t LocalTime) MarshalText() (text []byte, err error)

MarshalText implements encoding.TextMarshaler.

func (LocalTime) Millisecond

func (t LocalTime) Millisecond() int

Millisecond returns the millisecond component (0-999).

func (LocalTime) Minute

func (t LocalTime) Minute() int

Minute returns the minute component (0-59).

func (LocalTime) Nano added in v1.0.0

func (t LocalTime) Nano() int

Nano returns the nanosecond component (0-999999999).

func (LocalTime) NanoOfDay added in v1.0.0

func (t LocalTime) NanoOfDay() int64

func (*LocalTime) Scan

func (t *LocalTime) Scan(src any) error

Scan implements sql.Scanner for database deserialization.

func (LocalTime) Second

func (t LocalTime) Second() int

Second returns the second component (0-59).

func (LocalTime) SecondOfDay added in v1.0.0

func (t LocalTime) SecondOfDay() int

func (LocalTime) String

func (t LocalTime) String() string
Example

ExampleLocalTime_String demonstrates the string format with fractional seconds.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// LocalTime without fractional seconds
	t1 := goda.MustLocalTimeOf(14, 30, 45, 0)
	fmt.Println(t1)

	// LocalTime with milliseconds
	t2 := goda.MustLocalTimeOf(14, 30, 45, 123000000)
	fmt.Println(t2)

	// LocalTime with microseconds
	t3 := goda.MustLocalTimeOf(14, 30, 45, 123456000)
	fmt.Println(t3)

	// LocalTime with nanoseconds
	t4 := goda.MustLocalTimeOf(14, 30, 45, 123456789)
	fmt.Println(t4)

	// LocalTime with trailing zeros aligned to 3-digit boundaries
	t5 := goda.MustLocalTimeOf(14, 30, 45, 100000000)
	fmt.Println(t5)

}
Output:

14:30:45
14:30:45.123
14:30:45.123456
14:30:45.123456789
14:30:45.100

func (*LocalTime) UnmarshalJSON

func (t *LocalTime) UnmarshalJSON(bytes []byte) error

UnmarshalJSON implements json.Unmarshaler.

Example

ExampleLocalTime_UnmarshalJSON demonstrates JSON deserialization.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	var t goda.LocalTime
	jsonData := []byte(`"14:30:45.123456789"`)
	err := json.Unmarshal(jsonData, &t)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(t)

}
Output:

14:30:45.123456789

func (*LocalTime) UnmarshalText

func (t *LocalTime) UnmarshalText(text []byte) (e error)

UnmarshalText implements encoding.TextUnmarshaler.

func (LocalTime) Value

func (t LocalTime) Value() (driver.Value, error)

Value implements driver.Valuer for database serialization.

type LocalTimeChain added in v1.0.0

type LocalTimeChain struct {
	Chain[LocalTime]
}

func (LocalTimeChain) MinusHours added in v1.0.0

func (l LocalTimeChain) MinusHours(hoursToSubtract int64) LocalTimeChain

func (LocalTimeChain) MinusMinutes added in v1.0.0

func (l LocalTimeChain) MinusMinutes(minutesToSubtract int64) LocalTimeChain

func (LocalTimeChain) MinusNano added in v1.0.0

func (l LocalTimeChain) MinusNano(nanosToSubtract int64) LocalTimeChain

func (LocalTimeChain) MinusSeconds added in v1.0.0

func (l LocalTimeChain) MinusSeconds(secondsToSubtract int64) LocalTimeChain

func (LocalTimeChain) PlusHours added in v1.0.0

func (l LocalTimeChain) PlusHours(hours int64) LocalTimeChain

func (LocalTimeChain) PlusMinutes added in v1.0.0

func (l LocalTimeChain) PlusMinutes(minutesToAdd int64) LocalTimeChain

func (LocalTimeChain) PlusNano added in v1.0.0

func (l LocalTimeChain) PlusNano(nanosToAdd int64) LocalTimeChain

func (LocalTimeChain) PlusSeconds added in v1.0.0

func (l LocalTimeChain) PlusSeconds(secondsToAdd int64) LocalTimeChain

func (LocalTimeChain) WithField added in v1.0.0

func (l LocalTimeChain) WithField(field Field, value TemporalValue) LocalTimeChain

WithField returns a copy of this LocalTime with the specified field replaced. Zero values return zero immediately.

Supported fields mirror Java's LocalTime#with(TemporalField, long):

  • FieldNanoOfSecond: sets the nano-of-second while keeping hour, minute, and second.
  • FieldNanoOfDay: replaces the entire time using the provided nano-of-day (equivalent to LocalTimeOfNanoOfDay).
  • FieldMicroOfSecond: replaces the nano-of-second with micro-of-second × 1,000; hour, minute, and second stay the same.
  • FieldMicroOfDay: replaces the entire time using micro-of-day × 1,000 (equivalent to LocalTimeOfNanoOfDay).
  • FieldMilliOfSecond: replaces the nano-of-second with milli-of-second × 1,000,000; hour, minute, and second stay the same.
  • FieldMilliOfDay: replaces the entire time using milli-of-day × 1,000,000 (equivalent to LocalTimeOfNanoOfDay).
  • FieldSecondOfMinute: sets the second-of-minute while leaving hour, minute, and nano-of-second untouched.
  • FieldSecondOfDay: replaces hour, minute, and second based on the provided second-of-day while keeping nano-of-second.
  • FieldMinuteOfHour: sets the minute-of-hour; hour, second, and nano-of-second stay unchanged.
  • FieldMinuteOfDay: replaces hour and minute based on the minute-of-day; second and nano-of-second stay unchanged.
  • FieldHourOfAmPm: sets the hour within AM/PM while keeping the current half of day, minute, second, and nano-of-second.
  • FieldClockHourOfAmPm: sets the 1-12 clock hour within AM/PM while keeping the current half of day, minute, second, and nano-of-second.
  • FieldHourOfDay: sets the hour-of-day while leaving minute, second, and nano-of-second untouched.
  • FieldClockHourOfDay: sets the 1-24 clock hour-of-day (24 → 0) while leaving minute, second, and nano-of-second untouched.
  • FieldAmPmOfDay: toggles AM/PM while preserving the hour-of-am-pm, minute, second, and nano-of-second.

Fields outside this list return an error. Range violations propagate the validation error.

Example

ExampleLocalTimeChain_WithField demonstrates mutating LocalTime components using WithField.

package main

import (
	"fmt"
	"time"

	"github.com/iseki0/goda"
)

func main() {
	morning := goda.MustLocalTimeOf(7, 30, 45, 123000000)

	toEvening, _ := morning.Chain().WithField(goda.FieldAmPmOfDay, goda.TemporalValueOf(1)).GetResult()
	withDifferentNanos, _ := morning.Chain().WithField(goda.FieldNanoOfSecond, goda.TemporalValueOf(987654321)).GetResult()
	exactTime, _ := morning.Chain().WithField(goda.FieldNanoOfDay, goda.TemporalValueOf(int64(22*time.Hour+1*time.Minute))).GetResult()

	fmt.Println(toEvening)
	fmt.Println(withDifferentNanos)
	fmt.Println(exactTime)

}
Output:

19:30:45.123
07:30:45.987654321
22:01:00

func (LocalTimeChain) WithHour added in v1.0.0

func (l LocalTimeChain) WithHour(hour int) LocalTimeChain

func (LocalTimeChain) WithMinute added in v1.0.0

func (l LocalTimeChain) WithMinute(minute int) LocalTimeChain

func (LocalTimeChain) WithNano added in v1.0.0

func (l LocalTimeChain) WithNano(nanoOfSecond int) LocalTimeChain

func (LocalTimeChain) WithSecond added in v1.0.0

func (l LocalTimeChain) WithSecond(second int) LocalTimeChain

type Month

type Month time.Month

Month represents a month-of-year in the ISO-8601 calendar system, such as January or December. It is compatible with time.Month.

Example

ExampleMonth demonstrates working with months.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Months are constants from January (1) to December (12)
	fmt.Println("January:", goda.January)
	fmt.Println("December:", goda.December)

	// Get month length
	fmt.Println("Days in February (non-leap):", goda.February.Length(false))
	fmt.Println("Days in February (leap):", goda.February.Length(true))

}
Output:

January: January
December: December
Days in February (non-leap): 28
Days in February (leap): 29
const (
	January   Month = iota + 1 // January (month 1)
	February                   // February (month 2)
	March                      // March (month 3)
	April                      // April (month 4)
	May                        // May (month 5)
	June                       // June (month 6)
	July                       // July (month 7)
	August                     // August (month 8)
	September                  // September (month 9)
	October                    // October (month 10)
	November                   // November (month 11)
	December                   // December (month 12)
)

Month constants.

func (Month) FirstDayOfYear

func (m Month) FirstDayOfYear(isLeap bool) int

FirstDayOfYear returns the day-of-year (1-366) for the first day of this month. The isLeap parameter indicates whether the year is a leap year. For example, March 1st is day 60 in non-leap years and day 61 in leap years.

func (Month) IsZero

func (m Month) IsZero() bool

IsZero returns true if this is the zero value (not a valid month).

func (Month) Length

func (m Month) Length(isLeap bool) int

Length returns the number of days in this month for the specified year type. The isLeap parameter indicates whether the year is a leap year. February returns 29 for leap years and 28 for non-leap years. Other months return their fixed number of days.

func (Month) MaxDays

func (m Month) MaxDays() int

MaxDays returns the maximum days in the month. For February, it returns 29 (leap year maximum). For other months, it returns the fixed number of days.

func (Month) String

func (m Month) String() string

String returns the English name of the month (e.g., "January", "February"). Returns empty string for zero value.

type OffsetDateTime added in v0.0.6

type OffsetDateTime struct {
	// contains filtered or unexported fields
}

OffsetDateTime represents a date-time with a time-zone offset from UTC, such as 2024-03-15T14:30:45.123456789+01:00.

OffsetDateTime stores an offset from UTC, but does not store or use a time-zone. Use ZonedDateTime when you need full time-zone support including DST transitions.

OffsetDateTime is comparable and can be used as a map key. The zero value represents an unset date-time and IsZero returns true for it.

OffsetDateTime implements sql.Scanner and driver.Valuer for database operations, encoding.TextMarshaler and encoding.TextUnmarshaler for text serialization, and json.Marshaler and json.Unmarshaler for JSON serialization.

Format: yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn]±HH:mm (e.g., "2024-03-15T14:30:45.123456789+01:00").

Example

ExampleOffsetDateTime demonstrates basic OffsetDateTime usage.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Create from components
	offset := goda.MustZoneOffsetOfHours(8) // +08:00 (China Standard Time)
	odt := goda.MustOffsetDateTimeOf(2024, goda.March, 15, 14, 30, 45, 0, offset)
	fmt.Println(odt)

	// Create from LocalDateTime
	dt := goda.MustLocalDateTimeOf(2024, goda.March, 15, 14, 30, 45, 0)
	odt2 := dt.AtOffset(offset)
	fmt.Println(odt2)

	// Parse from string
	odt3 := goda.MustOffsetDateTimeParse("2024-03-15T14:30:45+08:00")
	fmt.Println(odt3)

	// UTC
	utcOdt := goda.MustOffsetDateTimeParse("2024-03-15T14:30:45Z")
	fmt.Println(utcOdt)

}
Output:

2024-03-15T14:30:45+08:00
2024-03-15T14:30:45+08:00
2024-03-15T14:30:45+08:00
2024-03-15T14:30:45Z

func MustOffsetDateTimeOf added in v1.0.0

func MustOffsetDateTimeOf(year Year, month Month, day int, hour int, minute int, second int, nanosecond int, offset ZoneOffset) OffsetDateTime

MustOffsetDateTimeOf creates a new OffsetDateTime from individual components. Panics if any component is invalid.

func MustOffsetDateTimeParse added in v1.0.0

func MustOffsetDateTimeParse(s string) OffsetDateTime

MustOffsetDateTimeParse parses a date-time string with offset. Panics if the string is invalid.

func OffsetDateTimeNow added in v0.0.6

func OffsetDateTimeNow() OffsetDateTime

OffsetDateTimeNow returns the current date-time with offset in the system's local time zone.

Example

ExampleOffsetDateTimeNow demonstrates getting the current time with offset.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Get current time with system's local offset
	now := goda.OffsetDateTimeNow()
	fmt.Printf("Has current time: %v\n", !now.IsZero())

	// Get current UTC time
	utcNow := goda.OffsetDateTimeNowUTC()
	fmt.Printf("UTC offset: %d seconds\n", utcNow.Offset().TotalSeconds())

}
Output:

Has current time: true
UTC offset: 0 seconds

func OffsetDateTimeNowUTC added in v0.0.6

func OffsetDateTimeNowUTC() OffsetDateTime

OffsetDateTimeNowUTC returns the current date-time with offset in UTC.

func OffsetDateTimeOf added in v1.0.0

func OffsetDateTimeOf(year Year, month Month, day int, hour int, minute int, second int, nanosecond int, offset ZoneOffset) (OffsetDateTime, error)

OffsetDateTimeOf creates a new OffsetDateTime from individual components. Returns an error if any component is invalid.

func OffsetDateTimeOfGoTime added in v0.0.11

func OffsetDateTimeOfGoTime(t time.Time) OffsetDateTime

OffsetDateTimeOfGoTime creates an OffsetDateTime from a time.Time. Returns zero value if t.IsZero().

func OffsetDateTimeParse added in v1.0.0

func OffsetDateTimeParse(s string) (OffsetDateTime, error)

OffsetDateTimeParse parses a date-time string in RFC3339-compatible format. The format is yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn]±HH:mm[:ss] or with 'Z' for UTC.

Examples:

odt, err := OffsetDateTimeParse("2024-03-15T14:30:45.123456789+01:00")
odt, err := OffsetDateTimeParse("2024-03-15T14:30:45Z")
odt, err := OffsetDateTimeParse("2024-03-15T14:30:45+05:30")
Example

ExampleOffsetDateTimeParse demonstrates parsing offset date-times.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// With positive offset
	odt1, _ := goda.OffsetDateTimeParse("2024-03-15T14:30:45+08:00")
	fmt.Println(odt1)

	// With negative offset
	odt2, _ := goda.OffsetDateTimeParse("2024-03-15T14:30:45-05:00")
	fmt.Println(odt2)

	// UTC (Z)
	odt3, _ := goda.OffsetDateTimeParse("2024-03-15T14:30:45Z")
	fmt.Println(odt3)

	// With minutes offset
	odt4, _ := goda.OffsetDateTimeParse("2024-03-15T14:30:45+05:30")
	fmt.Println(odt4)

}
Output:

2024-03-15T14:30:45+08:00
2024-03-15T14:30:45-05:00
2024-03-15T14:30:45Z
2024-03-15T14:30:45+05:30

func (OffsetDateTime) AppendText added in v0.0.6

func (odt OffsetDateTime) AppendText(b []byte) ([]byte, error)

AppendText implements encoding.TextAppender.

func (OffsetDateTime) Chain added in v1.0.0

func (odt OffsetDateTime) Chain() (chain OffsetDateTimeChain)

func (OffsetDateTime) Compare added in v0.0.6

func (odt OffsetDateTime) Compare(other OffsetDateTime) int

Compare compares this offset date-time with another. The comparison is based on the instant then on the local date-time. Returns -1 if this is before other, 0 if equal, 1 if after.

Example

ExampleOffsetDateTime_Compare demonstrates comparing offset date-times.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// These represent the same instant in time
	odt1 := goda.MustOffsetDateTimeParse("2024-03-15T14:30:45+08:00")
	odt2 := goda.MustOffsetDateTimeParse("2024-03-15T06:30:45Z")

	if odt1.Compare(odt2) == 0 {
		fmt.Println("Same instant")
	}

	// Different instants
	odt3 := goda.MustOffsetDateTimeParse("2024-03-15T15:30:45+08:00")
	if odt3.IsAfter(odt1) {
		fmt.Println("odt3 is later")
	}

}
Output:

odt3 is later

func (OffsetDateTime) DayOfMonth added in v0.0.6

func (odt OffsetDateTime) DayOfMonth() int

DayOfMonth returns the day-of-month component.

func (OffsetDateTime) DayOfWeek added in v0.0.6

func (odt OffsetDateTime) DayOfWeek() DayOfWeek

DayOfWeek returns the day-of-week.

func (OffsetDateTime) DayOfYear added in v0.0.6

func (odt OffsetDateTime) DayOfYear() int

DayOfYear returns the day-of-year.

func (OffsetDateTime) EpochSecond added in v1.0.0

func (odt OffsetDateTime) EpochSecond() int64

EpochSecond returns the number of seconds since Unix epoch (1970-01-01T00:00:00Z).

Example

ExampleOffsetDateTime_EpochSecond demonstrates Unix timestamp conversion.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Different offsets, same instant
	odt1 := goda.MustOffsetDateTimeParse("2024-03-15T14:30:45+08:00")
	odt2 := goda.MustOffsetDateTimeParse("2024-03-15T06:30:45Z")

	epoch1 := odt1.EpochSecond()
	epoch2 := odt2.EpochSecond()

	fmt.Printf("Has epoch seconds: %v\n", epoch1 > 0)
	fmt.Printf("Same instant: %v\n", epoch1 == epoch2)

}
Output:

Has epoch seconds: true
Same instant: true

func (OffsetDateTime) GetField added in v0.0.11

func (odt OffsetDateTime) GetField(field Field) TemporalValue

GetField returns the value of the specified field as a TemporalValue. This method queries the date-time for the value of the specified field. The returned value may be unsupported if the field is not supported by OffsetDateTime.

If the date-time is zero (IsZero() returns true), an unsupported TemporalValue is returned.

OffsetDateTime supports all fields from LocalDateTime plus:

  • FieldOffsetSeconds: the offset in seconds
  • FieldInstantSeconds: the epoch seconds (Unix timestamp)

func (OffsetDateTime) GoTime added in v0.0.6

func (odt OffsetDateTime) GoTime() time.Time

GoTime converts this offset date-time to a time.Time. Returns time.Time{} (zero) for zero value.

func (OffsetDateTime) Hour added in v0.0.6

func (odt OffsetDateTime) Hour() int

Hour returns the hour component (0-23).

func (OffsetDateTime) IsAfter added in v0.0.6

func (odt OffsetDateTime) IsAfter(other OffsetDateTime) bool

IsAfter returns true if this offset date-time is after the specified offset date-time.

func (OffsetDateTime) IsBefore added in v0.0.6

func (odt OffsetDateTime) IsBefore(other OffsetDateTime) bool

IsBefore returns true if this offset date-time is before the specified offset date-time.

func (OffsetDateTime) IsLeapYear added in v0.0.6

func (odt OffsetDateTime) IsLeapYear() bool

IsLeapYear returns true if the year is a leap year.

func (OffsetDateTime) IsSupportedField added in v0.0.6

func (odt OffsetDateTime) IsSupportedField(field Field) bool

IsSupportedField returns true if the field is supported by OffsetDateTime. OffsetDateTime supports all fields from LocalDateTime plus FieldOffsetSeconds and FieldInstantSeconds.

func (OffsetDateTime) IsZero added in v0.0.6

func (odt OffsetDateTime) IsZero() bool

IsZero returns true if this is the zero value.

func (OffsetDateTime) LocalDate added in v0.0.6

func (odt OffsetDateTime) LocalDate() LocalDate

LocalDate returns the date part of this date-time.

func (OffsetDateTime) LocalDateTime added in v0.0.6

func (odt OffsetDateTime) LocalDateTime() LocalDateTime

LocalDateTime returns the local date-time part without the offset.

func (OffsetDateTime) LocalTime added in v0.0.6

func (odt OffsetDateTime) LocalTime() LocalTime

LocalTime returns the time part of this date-time.

func (OffsetDateTime) MarshalJSON added in v0.0.6

func (odt OffsetDateTime) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

Example

ExampleOffsetDateTime_MarshalJSON demonstrates JSON serialization.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	odt := goda.MustOffsetDateTimeParse("2024-03-15T14:30:45+08:00")
	jsonBytes, _ := json.Marshal(odt)
	fmt.Println(string(jsonBytes))

	// UTC
	utcOdt := goda.MustOffsetDateTimeParse("2024-03-15T14:30:45Z")
	utcBytes, _ := json.Marshal(utcOdt)
	fmt.Println(string(utcBytes))

}
Output:

"2024-03-15T14:30:45+08:00"
"2024-03-15T14:30:45Z"

func (OffsetDateTime) MarshalText added in v0.0.6

func (odt OffsetDateTime) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler.

func (OffsetDateTime) Millisecond added in v0.0.6

func (odt OffsetDateTime) Millisecond() int

Millisecond returns the millisecond component (0-999).

func (OffsetDateTime) Minute added in v0.0.6

func (odt OffsetDateTime) Minute() int

Minute returns the minute component (0-59).

func (OffsetDateTime) Month added in v0.0.6

func (odt OffsetDateTime) Month() Month

Month returns the month component.

func (OffsetDateTime) Nanosecond added in v0.0.6

func (odt OffsetDateTime) Nanosecond() int

Nanosecond returns the nanosecond component (0-999999999).

func (OffsetDateTime) Offset added in v0.0.6

func (odt OffsetDateTime) Offset() ZoneOffset

Offset returns the zone offset.

func (*OffsetDateTime) Scan added in v0.0.6

func (odt *OffsetDateTime) Scan(src any) error

Scan implements sql.Scanner.

func (OffsetDateTime) Second added in v0.0.6

func (odt OffsetDateTime) Second() int

Second returns the second component (0-59).

func (OffsetDateTime) String added in v0.0.6

func (odt OffsetDateTime) String() string

String returns the ISO 8601 string representation (yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn]±HH:mm).

func (*OffsetDateTime) UnmarshalJSON added in v0.0.6

func (odt *OffsetDateTime) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

Example

ExampleOffsetDateTime_UnmarshalJSON demonstrates JSON deserialization.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	jsonData := []byte(`"2024-03-15T14:30:45+08:00"`)

	var odt goda.OffsetDateTime
	_ = json.Unmarshal(jsonData, &odt)

	fmt.Printf("Year: %d\n", odt.Year())
	fmt.Printf("Offset: %d hours\n", odt.Offset().TotalSeconds()/3600)

}
Output:

Year: 2024
Offset: 8 hours

func (*OffsetDateTime) UnmarshalText added in v0.0.6

func (odt *OffsetDateTime) UnmarshalText(text []byte) (e error)

UnmarshalText implements encoding.TextUnmarshaler. Accepts ISO 8601 format: yyyy-MM-ddTHH:mm:ss[.nnnnnnnnn]±HH:mm[:ss] or Z for UTC.

func (OffsetDateTime) Value added in v0.0.6

func (odt OffsetDateTime) Value() (driver.Value, error)

Value implements driver.Valuer.

func (OffsetDateTime) Year added in v0.0.6

func (odt OffsetDateTime) Year() Year

Year returns the year component.

type OffsetDateTimeChain added in v1.0.0

type OffsetDateTimeChain struct {
	Chain[OffsetDateTime]
}

func (OffsetDateTimeChain) MinusDays added in v1.0.0

func (o OffsetDateTimeChain) MinusDays(days int64) OffsetDateTimeChain

func (OffsetDateTimeChain) MinusHours added in v1.0.0

func (o OffsetDateTimeChain) MinusHours(hours int64) OffsetDateTimeChain

func (OffsetDateTimeChain) MinusMinutes added in v1.0.0

func (o OffsetDateTimeChain) MinusMinutes(minutes int64) OffsetDateTimeChain

func (OffsetDateTimeChain) MinusMonths added in v1.0.0

func (o OffsetDateTimeChain) MinusMonths(months int64) OffsetDateTimeChain

func (OffsetDateTimeChain) MinusNanos added in v1.0.0

func (o OffsetDateTimeChain) MinusNanos(nanos int64) OffsetDateTimeChain

func (OffsetDateTimeChain) MinusSeconds added in v1.0.0

func (o OffsetDateTimeChain) MinusSeconds(seconds int64) OffsetDateTimeChain

func (OffsetDateTimeChain) MinusWeeks added in v1.0.0

func (o OffsetDateTimeChain) MinusWeeks(weeks int64) OffsetDateTimeChain

func (OffsetDateTimeChain) MinusYears added in v1.0.0

func (o OffsetDateTimeChain) MinusYears(years int64) OffsetDateTimeChain

func (OffsetDateTimeChain) PlusDays added in v1.0.0

func (OffsetDateTimeChain) PlusHours added in v1.0.0

func (o OffsetDateTimeChain) PlusHours(hours int64) OffsetDateTimeChain
Example

ExampleOffsetDateTimeChain_PlusHours demonstrates time arithmetic with hours.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	odt := goda.MustOffsetDateTimeParse("2024-03-15T14:30:45+08:00")

	// Add hours
	later := odt.Chain().PlusHours(5).MustGet()
	fmt.Println("5 hours later:", later)

	// Subtract hours
	earlier := odt.Chain().MinusHours(2).MustGet()
	fmt.Println("2 hours earlier:", earlier)

}
Output:

5 hours later: 2024-03-15T19:30:45+08:00
2 hours earlier: 2024-03-15T12:30:45+08:00

func (OffsetDateTimeChain) PlusMinutes added in v1.0.0

func (o OffsetDateTimeChain) PlusMinutes(minutes int64) OffsetDateTimeChain

func (OffsetDateTimeChain) PlusMonths added in v1.0.0

func (o OffsetDateTimeChain) PlusMonths(months int64) OffsetDateTimeChain

func (OffsetDateTimeChain) PlusNanos added in v1.0.0

func (o OffsetDateTimeChain) PlusNanos(nanos int64) OffsetDateTimeChain

func (OffsetDateTimeChain) PlusSeconds added in v1.0.0

func (o OffsetDateTimeChain) PlusSeconds(seconds int64) OffsetDateTimeChain

func (OffsetDateTimeChain) PlusWeeks added in v1.0.0

func (o OffsetDateTimeChain) PlusWeeks(weeks int64) OffsetDateTimeChain

func (OffsetDateTimeChain) PlusYears added in v1.0.0

func (o OffsetDateTimeChain) PlusYears(years int64) OffsetDateTimeChain

func (OffsetDateTimeChain) WithDayOfMonth added in v1.0.0

func (o OffsetDateTimeChain) WithDayOfMonth(dayOfMonth int) OffsetDateTimeChain

func (OffsetDateTimeChain) WithDayOfYear added in v1.0.0

func (o OffsetDateTimeChain) WithDayOfYear(dayOfYear int) OffsetDateTimeChain

func (OffsetDateTimeChain) WithField added in v1.0.0

func (o OffsetDateTimeChain) WithField(field Field, value TemporalValue) OffsetDateTimeChain

func (OffsetDateTimeChain) WithHour added in v1.0.0

func (o OffsetDateTimeChain) WithHour(hour int) OffsetDateTimeChain

func (OffsetDateTimeChain) WithMinute added in v1.0.0

func (o OffsetDateTimeChain) WithMinute(minute int) OffsetDateTimeChain

func (OffsetDateTimeChain) WithMonth added in v1.0.0

func (o OffsetDateTimeChain) WithMonth(month Month) OffsetDateTimeChain

func (OffsetDateTimeChain) WithNano added in v1.0.0

func (o OffsetDateTimeChain) WithNano(nanoOfSecond int) OffsetDateTimeChain

func (OffsetDateTimeChain) WithSecond added in v1.0.0

func (o OffsetDateTimeChain) WithSecond(second int) OffsetDateTimeChain

func (OffsetDateTimeChain) WithYear added in v1.0.0

func (o OffsetDateTimeChain) WithYear(year Year) OffsetDateTimeChain

type TemporalAccessor added in v0.0.8

type TemporalAccessor interface {
	// IsZero returns true if this temporal object represents a zero/unset value.
	IsZero() bool

	// IsSupportedField checks if the specified field is supported by this temporal type.
	// For example, LocalDate supports date fields but not time fields.
	IsSupportedField(field Field) bool

	// GetField returns the value of the specified field.
	// If the field is not supported or the temporal is zero, returns an unsupported TemporalValue.
	GetField(field Field) TemporalValue
}

TemporalAccessor provides read-only access to date and time fields. This interface is implemented by types that can provide field-based access to their components, such as LocalDate, LocalTime, LocalDateTime, and OffsetDateTime.

The accessor pattern allows querying date/time components in a uniform way across different temporal types. For example, both LocalDate and LocalDateTime support querying the year field, but only LocalDateTime supports querying time fields.

This is similar to Java's TemporalAccessor interface.

type TemporalValue added in v0.0.8

type TemporalValue struct {
	// contains filtered or unexported fields
}

TemporalValue represents the value of a temporal field, with support for overflow and unsupported field states.

TemporalValue is returned by TemporalAccessor.GetField() and used by temporal types that support field-based mutation. It provides a safe way to handle field values that may be out of range or unsupported.

The value can be in one of three states:

  • Valid: Contains a normal field value
  • Overflow: The value is too large to fit in an int64
  • Unsupported: The field is not supported by the temporal type

Use Valid(), Overflow(), and Unsupported() methods to check the state. Use Int() or Int64() to get the value when Valid() returns true.

func TemporalValueOf added in v1.0.0

func TemporalValueOf[T interface {
	int | int64 | int32 | int16 | int8
}](v T) TemporalValue

TemporalValueOf creates a new TemporalValue from an integer type. The resulting value will be valid (neither overflow nor unsupported).

func (TemporalValue) Int added in v0.0.8

func (t TemporalValue) Int() int

Int returns the value as an int. Only call this when Valid() returns true and the value fits in an int.

func (TemporalValue) Int64 added in v0.0.8

func (t TemporalValue) Int64() int64

Int64 returns the value as an int64. Only call this when Valid() returns true.

func (TemporalValue) Overflow added in v0.0.8

func (t TemporalValue) Overflow() bool

Overflow returns true if the field value overflowed and cannot be represented. When this returns true, the value is undefined.

func (TemporalValue) Unsupported added in v0.0.8

func (t TemporalValue) Unsupported() bool

Unsupported returns true if the field is not supported by the temporal type. When this returns true, no meaningful value is available.

func (TemporalValue) Valid added in v0.0.8

func (t TemporalValue) Valid() bool

Valid returns true if the value is valid and can be safely accessed. Valid() is equivalent to !Unsupported() && !Overflow().

type Year

type Year int64

Year represents a year in the ISO-8601 calendar system. It can represent any year from math.MinInt64 to math.MaxInt64.

func (Year) AppendText

func (y Year) AppendText(b []byte) ([]byte, error)

AppendText implements the encoding.TextAppender interface. It appends the year representation to b and returns the extended buffer.

func (Year) Int

func (y Year) Int() int

Int returns this year as an int.

func (Year) Int64

func (y Year) Int64() int64

Int64 returns this year as an int64.

func (Year) IsLeapYear

func (y Year) IsLeapYear() bool

IsLeapYear returns true if this year is a leap year. A leap year is divisible by 4, unless it's divisible by 100 (but not 400). For example: 2024 is a leap year, 1900 is not, but 2000 is.

Example

ExampleYear_IsLeapYear demonstrates checking for leap years.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	fmt.Println("2024 is leap:", goda.Year(2024).IsLeapYear())
	fmt.Println("2023 is leap:", goda.Year(2023).IsLeapYear())
	fmt.Println("2000 is leap:", goda.Year(2000).IsLeapYear())
	fmt.Println("1900 is leap:", goda.Year(1900).IsLeapYear())

}
Output:

2024 is leap: true
2023 is leap: false
2000 is leap: true
1900 is leap: false

func (Year) Length

func (y Year) Length() int

Length returns the number of days in this year (365 or 366).

func (Year) String

func (y Year) String() string

String returns the string representation of this year. Years 0-9999 are formatted as 4 digits with leading zeros (e.g., "0001", "2024"). Years outside this range are formatted without padding.

type YearMonth added in v1.0.0

type YearMonth struct {
	// contains filtered or unexported fields
}

func MustYearMonthOf added in v1.0.0

func MustYearMonthOf(year Year, month Month) YearMonth

func YearMonthOf added in v1.0.0

func YearMonthOf(year Year, month Month) (y YearMonth, e error)

func (YearMonth) AppendText added in v1.0.0

func (y YearMonth) AppendText(b []byte) ([]byte, error)

func (YearMonth) Chain added in v1.0.0

func (y YearMonth) Chain() (chain YearMonthChain)

func (YearMonth) Compare added in v1.0.0

func (y YearMonth) Compare(other YearMonth) int

func (YearMonth) IsLeapYear added in v1.0.0

func (y YearMonth) IsLeapYear() bool

func (YearMonth) IsZero added in v1.0.0

func (y YearMonth) IsZero() bool

func (YearMonth) LengthOfMonth added in v1.0.0

func (y YearMonth) LengthOfMonth() int

func (YearMonth) LengthOfYear added in v1.0.0

func (y YearMonth) LengthOfYear() int

func (YearMonth) MarshalJSON added in v1.0.0

func (y YearMonth) MarshalJSON() ([]byte, error)

func (YearMonth) MarshalText added in v1.0.0

func (y YearMonth) MarshalText() (text []byte, err error)

func (YearMonth) Month added in v1.0.0

func (y YearMonth) Month() Month

func (YearMonth) ProlepticMonth added in v1.0.0

func (y YearMonth) ProlepticMonth() int64

func (*YearMonth) Scan added in v1.0.0

func (y *YearMonth) Scan(src any) error

func (YearMonth) String added in v1.0.0

func (y YearMonth) String() string

func (*YearMonth) UnmarshalJSON added in v1.0.0

func (y *YearMonth) UnmarshalJSON(i []byte) error

func (*YearMonth) UnmarshalText added in v1.0.0

func (y *YearMonth) UnmarshalText(text []byte) (e error)

func (YearMonth) Value added in v1.0.0

func (y YearMonth) Value() (driver.Value, error)

func (YearMonth) Year added in v1.0.0

func (y YearMonth) Year() Year

type YearMonthChain added in v1.0.0

type YearMonthChain struct {
	Chain[YearMonth]
}

func (YearMonthChain) MinusMonths added in v1.0.0

func (y YearMonthChain) MinusMonths(months int64) YearMonthChain

func (YearMonthChain) MinusYears added in v1.0.0

func (y YearMonthChain) MinusYears(years int64) YearMonthChain

func (YearMonthChain) PlusMonths added in v1.0.0

func (y YearMonthChain) PlusMonths(months int64) YearMonthChain

func (YearMonthChain) PlusYears added in v1.0.0

func (y YearMonthChain) PlusYears(years int64) YearMonthChain

func (YearMonthChain) WithField added in v1.0.0

func (y YearMonthChain) WithField(field Field, value TemporalValue) YearMonthChain

func (YearMonthChain) WithMonth added in v1.0.0

func (y YearMonthChain) WithMonth(month Month) YearMonthChain

func (YearMonthChain) WithYear added in v1.0.0

func (y YearMonthChain) WithYear(year Year) YearMonthChain

type ZoneId added in v1.0.0

type ZoneId struct {
	// contains filtered or unexported fields
}

ZoneId represents a time zone identifier such as "America/New_York" or "Asia/Tokyo". It wraps a time.Location and provides serialization support for JSON, text, and SQL.

ZoneId is comparable and can be used as a map key. The zero value represents an unset zone and IsZero returns true for it.

ZoneId implements sql.Scanner and driver.Valuer for database operations, encoding.TextMarshaler and encoding.TextUnmarshaler for text serialization, encoding.TextAppender for efficient text appending, and json.Marshaler and json.Unmarshaler for JSON serialization.

Format: Uses IANA Time Zone Database names (e.g., "America/New_York", "Europe/London", "UTC"). The string representation matches Go's time.Location.String() format.

Example

ExampleZoneId demonstrates basic ZoneId usage.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Create zone IDs for different time zones
	newYork, _ := goda.ZoneIdOf("America/New_York")
	fmt.Println("New York:", newYork)

	tokyo := goda.MustZoneIdOf("Asia/Tokyo")
	fmt.Println("Tokyo:", tokyo)

	// UTC is a common zone
	utc := goda.ZoneIdUTC()
	fmt.Println("UTC:", utc)

	// Get system's default zone
	defaultZone := goda.ZoneIdDefault()
	fmt.Printf("Has default zone: %v\n", !defaultZone.IsZero())

}
Output:

New York: America/New_York
Tokyo: Asia/Tokyo
UTC: UTC
Has default zone: true
Example (RoundTrip)

ExampleZoneId_roundTrip demonstrates serialization round-trip.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Original zone
	original := goda.MustZoneIdOf("Pacific/Auckland")

	// Serialize to JSON
	jsonData, _ := json.Marshal(original)

	// Deserialize from JSON
	var restored goda.ZoneId
	_ = json.Unmarshal(jsonData, &restored)

	// Compare
	fmt.Println("Original:", original)
	fmt.Println("Restored:", restored)
	fmt.Println("Same:", original.String() == restored.String())

}
Output:

Original: Pacific/Auckland
Restored: Pacific/Auckland
Same: true

func MustZoneIdOf added in v1.0.0

func MustZoneIdOf(id string) ZoneId

MustZoneIdOf creates a ZoneId from a time zone identifier string. Panics if the zone ID is invalid. Use ZoneIdOf for error handling.

Example

ExampleMustZoneIdOf demonstrates creating a ZoneId that panics on error.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Valid zone ID
	zone := goda.MustZoneIdOf("Asia/Shanghai")
	fmt.Println(zone)

}
Output:

Asia/Shanghai

func ZoneIdDefault added in v1.0.0

func ZoneIdDefault() ZoneId

ZoneIdDefault returns the system's default time zone. This corresponds to time.Local in Go's standard library. If time.Local is nil, returns ZoneIdUTC.

Example

ExampleZoneIdDefault demonstrates getting the system's default zone.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	defaultZone := goda.ZoneIdDefault()
	fmt.Printf("Has default zone: %v\n", !defaultZone.IsZero())
	fmt.Printf("Zone name not empty: %v\n", defaultZone.String() != "")

}
Output:

Has default zone: true
Zone name not empty: true

func ZoneIdOf added in v1.0.0

func ZoneIdOf(id string) (ZoneId, error)

ZoneIdOf creates a ZoneId from a time zone identifier string. The identifier must be a valid IANA Time Zone Database name (e.g., "America/New_York", "Asia/Tokyo"). Returns an error if the zone ID is not found in the system's time zone database.

Example zone IDs:

  • "America/New_York" - Eastern Time
  • "Europe/London" - British Time
  • "Asia/Tokyo" - Japan Standard Time
  • "UTC" - Coordinated Universal Time
Example

ExampleZoneIdOf demonstrates creating a ZoneId from a string.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Valid zone ID
	zone, err := goda.ZoneIdOf("Europe/London")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Zone:", zone)

	// Invalid zone ID returns error
	_, err = goda.ZoneIdOf("Invalid/Zone")
	if err != nil {
		fmt.Println("Got expected error for invalid zone")
	}

}
Output:

Zone: Europe/London
Got expected error for invalid zone

func ZoneIdOfGoLocation added in v1.0.0

func ZoneIdOfGoLocation(l *time.Location) ZoneId

ZoneIdOfGoLocation creates a ZoneId from a Go time.Location. This allows interoperability with Go's standard time package.

Example

ExampleZoneIdOfGoLocation demonstrates creating a ZoneId from time.Location.

package main

import (
	"fmt"
	"time"

	"github.com/iseki0/goda"
)

func main() {
	// From Go's time.UTC
	utcZone := goda.ZoneIdOfGoLocation(time.UTC)
	fmt.Println("UTC:", utcZone)

	// From Go's time.Local
	localZone := goda.ZoneIdOfGoLocation(time.Local)
	fmt.Printf("Has local zone: %v\n", !localZone.IsZero())

	// From loaded location
	paris, _ := time.LoadLocation("Europe/Paris")
	parisZone := goda.ZoneIdOfGoLocation(paris)
	fmt.Println("Paris:", parisZone)

}
Output:

UTC: UTC
Has local zone: true
Paris: Europe/Paris

func ZoneIdUTC added in v1.0.0

func ZoneIdUTC() ZoneId

ZoneIdUTC returns a ZoneId representing UTC (Coordinated Universal Time).

Example

ExampleZoneIdUTC demonstrates getting the UTC zone.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	utc := goda.ZoneIdUTC()
	fmt.Println("Zone:", utc)
	fmt.Println("Is UTC:", utc.String() == "UTC")

}
Output:

Zone: UTC
Is UTC: true

func (ZoneId) AppendText added in v1.0.0

func (z ZoneId) AppendText(b []byte) ([]byte, error)

AppendText implements the encoding.TextAppender interface. It appends the zone ID to b and returns the extended buffer.

func (ZoneId) IsZero added in v1.0.0

func (z ZoneId) IsZero() bool

IsZero returns true if this is the zero value of ZoneId (no location set).

Example

ExampleZoneId_IsZero demonstrates checking for zero value.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Zero value
	var zero goda.ZoneId
	fmt.Println("Zero is zero:", zero.IsZero())

	// Non-zero value
	zone := goda.ZoneIdUTC()
	fmt.Println("UTC is zero:", zone.IsZero())

}
Output:

Zero is zero: true
UTC is zero: false

func (ZoneId) MarshalJSON added in v1.0.0

func (z ZoneId) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface. It returns the zone ID as a JSON string, or empty string for zero value.

Example

ExampleZoneId_MarshalJSON demonstrates JSON serialization.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	zone := goda.MustZoneIdOf("Asia/Singapore")
	jsonBytes, _ := json.Marshal(zone)
	fmt.Println(string(jsonBytes))

	// Zero value
	var zero goda.ZoneId
	zeroBytes, _ := json.Marshal(zero)
	fmt.Println(string(zeroBytes))

}
Output:

"Asia/Singapore"
""

func (ZoneId) MarshalText added in v1.0.0

func (z ZoneId) MarshalText() (text []byte, err error)

MarshalText implements the encoding.TextMarshaler interface. It returns the zone ID as text, or empty for zero value.

func (*ZoneId) Scan added in v1.0.0

func (z *ZoneId) Scan(src any) error

Scan implements the sql.Scanner interface. It supports scanning from nil, string, and []byte. Nil values are converted to the zero value of ZoneId.

func (ZoneId) String added in v1.0.0

func (z ZoneId) String() string

String returns the zone ID as a string, or empty string for zero value.

Example

ExampleZoneId_String demonstrates getting the string representation.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Various zones
	zones := []string{
		"America/New_York",
		"Europe/London",
		"Asia/Tokyo",
		"Australia/Sydney",
	}

	for _, name := range zones {
		zone := goda.MustZoneIdOf(name)
		fmt.Println(zone.String())
	}

}
Output:

America/New_York
Europe/London
Asia/Tokyo
Australia/Sydney

func (*ZoneId) UnmarshalJSON added in v1.0.0

func (z *ZoneId) UnmarshalJSON(bytes []byte) error

UnmarshalJSON implements the json.Unmarshaler interface. It accepts JSON strings representing a zone ID or JSON null.

Example

ExampleZoneId_UnmarshalJSON demonstrates JSON deserialization.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// From JSON string
	var zone goda.ZoneId
	err := json.Unmarshal([]byte(`"Europe/Berlin"`), &zone)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Zone:", zone)

	// From JSON null
	var nullZone goda.ZoneId
	_ = json.Unmarshal([]byte(`null`), &nullZone)
	fmt.Println("Null is zero:", nullZone.IsZero())

}
Output:

Zone: Europe/Berlin
Null is zero: true

func (*ZoneId) UnmarshalText added in v1.0.0

func (z *ZoneId) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface. It parses zone IDs. Empty input is treated as zero value.

func (ZoneId) Value added in v1.0.0

func (z ZoneId) Value() (driver.Value, error)

Value implements the driver.Valuer interface. It returns nil for zero values, otherwise returns the zone ID as a string.

type ZoneOffset added in v0.0.6

type ZoneOffset struct {
	// contains filtered or unexported fields
}

ZoneOffset represents a time-zone offset from UTC, such as +02:00.

A time-zone offset is the amount of time that a time-zone differs from Greenwich/UTC. This is usually a fixed number of hours and minutes.

Different parts of the world have different time-zone offsets. The rules for how offsets vary by place and time of year are captured in the ZoneId class.

For example, Paris is one hour ahead of Greenwich/UTC in winter and two hours ahead in summer. The ZoneId instance for Paris will reference two ZoneOffset instances - a +01:00 instance for winter, and a +02:00 instance for summer.

ZoneOffset is comparable and can be used as a map key. The zero value represents UTC (+00:00).

ZoneOffset implements sql.Scanner and driver.Valuer for database operations, encoding.TextMarshaler and encoding.TextUnmarshaler for text serialization, and json.Marshaler and json.Unmarshaler for JSON serialization.

Format: ±HH:mm, ±HH:mm:ss, or Z for UTC (e.g., "+02:00", "-05:30", "Z"). The seconds field is output only if non-zero.

Example

ExampleZoneOffset demonstrates basic ZoneOffset usage.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Create zone offsets
	utc := goda.ZoneOffsetUTC()
	fmt.Println("UTC:", utc)

	// From hours
	est := goda.MustZoneOffsetOfHours(-5)
	fmt.Println("EST:", est)

	// From hours and minutes
	ist := goda.MustZoneOffsetOfHoursMinutes(5, 30)
	fmt.Println("IST:", ist)

	// From total seconds
	jst := goda.MustZoneOffsetOfSeconds(9 * 3600)
	fmt.Println("JST:", jst)

}
Output:

UTC: Z
EST: -05:00
IST: +05:30
JST: +09:00

func MustZoneOffsetOf added in v0.0.11

func MustZoneOffsetOf(hours, minutes, seconds int) ZoneOffset

MustZoneOffsetOf creates a ZoneOffset from hours, minutes, and seconds. Panics if the offset is invalid.

func MustZoneOffsetOfHours added in v0.0.11

func MustZoneOffsetOfHours(hours int) ZoneOffset

MustZoneOffsetOfHours creates a ZoneOffset from hours only. Panics if the offset is invalid.

func MustZoneOffsetOfHoursMinutes added in v0.0.11

func MustZoneOffsetOfHoursMinutes(hours, minutes int) ZoneOffset

MustZoneOffsetOfHoursMinutes creates a ZoneOffset from hours and minutes. Panics if the offset is invalid.

func MustZoneOffsetOfSeconds added in v0.0.11

func MustZoneOffsetOfSeconds(seconds int) ZoneOffset

MustZoneOffsetOfSeconds creates a ZoneOffset from the total offset in seconds. Panics if the offset is outside the valid range.

func MustZoneOffsetParse added in v1.0.0

func MustZoneOffsetParse(s string) ZoneOffset

MustZoneOffsetParse parses a zone offset string. Panics if the string is invalid.

func ZoneOffsetMax added in v0.0.11

func ZoneOffsetMax() ZoneOffset

ZoneOffsetMax returns the maximum supported offset (+18:00).

func ZoneOffsetMin added in v0.0.11

func ZoneOffsetMin() ZoneOffset

ZoneOffsetMin returns the minimum supported offset (-18:00).

func ZoneOffsetOf added in v0.0.11

func ZoneOffsetOf(hours, minutes, seconds int) (r ZoneOffset, e error)

ZoneOffsetOf creates a ZoneOffset from hours, minutes, and seconds. The offset must be in the range -18:00 to +18:00.

The sign of all components must be the same. If any component is negative, all non-zero components must be negative or zero.

Returns an error if the offset is invalid.

func ZoneOffsetOfHours added in v0.0.11

func ZoneOffsetOfHours(hours int) (ZoneOffset, error)

ZoneOffsetOfHours creates a ZoneOffset from hours only. The offset must be in the range -18 to +18.

func ZoneOffsetOfHoursMinutes added in v0.0.11

func ZoneOffsetOfHoursMinutes(hours, minutes int) (ZoneOffset, error)

ZoneOffsetOfHoursMinutes creates a ZoneOffset from hours and minutes. The offset must be in the range -18:00 to +18:00.

func ZoneOffsetOfSeconds added in v0.0.11

func ZoneOffsetOfSeconds(seconds int) (r ZoneOffset, e error)

ZoneOffsetOfSeconds creates a ZoneOffset from the total offset in seconds. The offset must be in the range -18:00 to +18:00, which corresponds to -64800 to +64800 seconds.

Returns an error if the offset is outside the valid range.

func ZoneOffsetParse added in v1.0.0

func ZoneOffsetParse(s string) (ZoneOffset, error)

ZoneOffsetParse parses a zone offset string. Accepts the following formats:

  • Z: UTC
  • ±H: hour offset (-9, +9)
  • ±HH: hour offset (-09, +09)
  • ±HH:MM: hour and minute offset (-09:30, +09:30)
  • ±HHMM: hour and minute offset (-0930, +0930)
  • ±HH:MM:SS: hour, minute, and second offset (-09:30:45, +09:30:45)
  • ±HHMMSS: hour, minute, and second offset (-093045, +093045)

Returns an error if the string is invalid.

Example

ExampleZoneOffsetParse demonstrates parsing zone offsets.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	// Parse various formats
	z1 := goda.MustZoneOffsetParse("Z")
	fmt.Println("Z:", z1.TotalSeconds())

	z2 := goda.MustZoneOffsetParse("+02:00")
	fmt.Println("+02:00:", z2.TotalSeconds())

	z3 := goda.MustZoneOffsetParse("-05:30")
	fmt.Println("-05:30:", z3.TotalSeconds())

	z4 := goda.MustZoneOffsetParse("+0930")
	fmt.Println("+0930:", z4.TotalSeconds())

}
Output:

Z: 0
+02:00: 7200
-05:30: -19800
+0930: 34200

func ZoneOffsetUTC added in v0.0.6

func ZoneOffsetUTC() ZoneOffset

ZoneOffsetUTC returns UTC offset (+00:00).

func (ZoneOffset) AppendText added in v0.0.6

func (z ZoneOffset) AppendText(b []byte) ([]byte, error)

AppendText implements encoding.TextAppender.

func (ZoneOffset) Compare added in v0.0.11

func (z ZoneOffset) Compare(other ZoneOffset) int

Compare compares this zone offset with another. Returns -1 if this offset is less (more westward), 0 if equal, 1 if greater (more eastward).

Example

ExampleZoneOffset_Compare demonstrates comparing zone offsets.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	utc := goda.ZoneOffsetUTC()
	est := goda.MustZoneOffsetOfHours(-5)
	cet := goda.MustZoneOffsetOfHours(1)

	fmt.Printf("EST < UTC: %v\n", est.Compare(utc) < 0)
	fmt.Printf("CET > UTC: %v\n", cet.Compare(utc) > 0)
	fmt.Printf("EST < CET: %v\n", est.Compare(cet) < 0)

}
Output:

EST < UTC: true
CET > UTC: true
EST < CET: true

func (ZoneOffset) GetField added in v0.0.11

func (z ZoneOffset) GetField(field Field) TemporalValue

func (ZoneOffset) Hours added in v0.0.11

func (z ZoneOffset) Hours() int

Hours returns the hours component of the offset. For negative offsets, this returns a negative value.

func (ZoneOffset) IsSupportedField added in v0.0.11

func (z ZoneOffset) IsSupportedField(field Field) bool

func (ZoneOffset) IsZero added in v0.0.6

func (z ZoneOffset) IsZero() bool

IsZero returns true if this is the zero value (UTC). Note: This returns true for UTC (+00:00), not for invalid offsets.

func (ZoneOffset) MarshalJSON added in v0.0.6

func (z ZoneOffset) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

Example

ExampleZoneOffset_MarshalJSON demonstrates JSON serialization.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	offset := goda.MustZoneOffsetParse("+05:30")
	jsonBytes, _ := json.Marshal(offset)
	fmt.Println(string(jsonBytes))

}
Output:

"+05:30"

func (ZoneOffset) MarshalText added in v0.0.6

func (z ZoneOffset) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler.

func (ZoneOffset) Minutes added in v0.0.11

func (z ZoneOffset) Minutes() int

Minutes returns the minutes component of the offset (0-59). For negative offsets, this returns a negative value if the offset is not a whole number of hours.

func (ZoneOffset) Seconds added in v0.0.11

func (z ZoneOffset) Seconds() int

Seconds returns the seconds component of the offset (0-59). For negative offsets, this returns a negative value if the offset is not a whole number of minutes.

func (ZoneOffset) String added in v0.0.6

func (z ZoneOffset) String() string

String returns the string representation of the zone offset. Returns "Z" for UTC, otherwise returns the format ±HH:MM or ±HH:MM:SS.

func (ZoneOffset) TotalSeconds added in v0.0.6

func (z ZoneOffset) TotalSeconds() int

TotalSeconds returns the total zone offset in seconds.

Example

ExampleZoneOffset_TotalSeconds demonstrates accessing offset components.

package main

import (
	"fmt"

	"github.com/iseki0/goda"
)

func main() {
	offset := goda.MustZoneOffsetParse("+05:30")

	fmt.Println("Total seconds:", offset.TotalSeconds())
	fmt.Println("Hours:", offset.Hours())
	fmt.Println("Minutes:", offset.Minutes())
	fmt.Println("Seconds:", offset.Seconds())

}
Output:

Total seconds: 19800
Hours: 5
Minutes: 30
Seconds: 0

func (*ZoneOffset) UnmarshalJSON added in v0.0.6

func (z *ZoneOffset) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

func (*ZoneOffset) UnmarshalText added in v0.0.6

func (z *ZoneOffset) UnmarshalText(text []byte) (e error)

UnmarshalText implements encoding.TextUnmarshaler.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL