// Temporal component access and duration arithmetic: reading a named// component off an epoch-millis instant or a (months, days, millis)// duration, applying a duration to an instant (checked calendar add), and// the Euclidean integer-math helpers they share. Split from temporal.go,// which holds the ISO parsing and formatting.
package evalimport// Component is a temporal component accessor (.year/.month/.day/.hour/...// /.epochMillis) on an epoch-millis temporal; ok is false for an unknown// component (the caller yields Null).func ( int64, string) (int64, bool) { := floorDiv(, MSPerDay) := - *MSPerDay , , := CivilFromDays()switch {case"year":return , truecase"month":returnint64(), truecase"day":returnint64(), truecase"hour":return / 3_600_000, truecase"minute":return ( / 60_000) % 60, truecase"second":return ( / 1000) % 60, truecase"millisecond":return % 1000, truecase"epochMillis":return , truecase"epochSeconds":returnfloorDiv(, 1000), true }return0, false}// DurationComponent is a duration component accessor on a (months, days,// millis) duration, with the groups independent (Neo4j's convention): the// months group answers years/quarters/months (months is the group TOTAL,// so duration({years: 1}).months = 12), the days group weeks/days, and// the millis group hours/minutes/seconds/milliseconds (each the group// total at that unit, so PT2H reads .minutes = 120). ok=false for an// unknown component.func (, , int64, string) (int64, bool) {switch {case"years":return / 12, truecase"quarters":return / 3, truecase"months":return , truecase"weeks":return / 7, truecase"days":return , truecase"hours":return / 3_600_000, truecase"minutes":return / 60_000, truecase"seconds":return / 1000, truecase"milliseconds":return , true }return0, false}// ApplyDuration applies a duration (months, days, millis) to an// epoch-millis temporal, sign = +1 (add) or -1 (subtract). Months are a// calendar add (day clamped to the target month length, e.g. Jan 31 + 1// month = Feb 28); days and millis are absolute. Every step is checked:// ok=false on overflow, so the caller yields Null rather than a wrapped// nonsense instant. Note the boundary -- shifting a recent instant by// i64-scale milliseconds to a very negative-but-representable value is exact// and stays ok; only a genuine overflow declines.func (, , , , int64) (int64, bool) {// A months-free duration is pure tick arithmetic: with months == 0 the // civil round-trip below is the identity (no month carry, no day // clamp), so the result reduces to a single shifted addition.if == 0 { , := mulChk(, MSPerDay)if ! {return0, false }if , = addChk(, ); ! {return0, false }if , = mulChk(, ); ! {return0, false }returnaddChk(, ) } := floorDiv(, MSPerDay) := - *MSPerDay , , := CivilFromDays() , := mulChk(, )if ! {return0, false } , := addChk(int64()-1, )if ! {return0, false }// y0 is bounded (a representable instant) and floorDiv(total, 12) fits, // so this sum cannot overflow; the range guard below rejects an absurd // year before DaysFromCivil's era term can overflow. := + floorDiv(, 12)if < -maxCivilYear || > maxCivilYear {return0, false } := uint32(floorMod(, 12) + 1) := if := DaysInMonth(, ); > { = } , := mulChk(, )if ! {return0, false } , := addChk(DaysFromCivil(, , ), )if ! {return0, false } , := mulChk(, MSPerDay)if ! {return0, false }if , = addChk(, ); ! {return0, false } , := mulChk(, )if ! {return0, false }returnaddChk(, )}// floorDiv is Euclidean-style division rounding toward negative infinity// (Rust's div_euclid for positive divisors).func floorDiv(, int64) int64 { := / if % != 0 && ( < 0) != ( < 0) { -- }return}// floorMod is the non-negative remainder matching floorDiv.func floorMod(, int64) int64 {return - floorDiv(, )*}// parseI64 parses a decimal integer with optional sign and surrounding// spaces, comma-ok.func parseI64( string) (int64, bool) { = strings.TrimSpace()if == "" {return0, false } := falseif [0] == '+' || [0] == '-' { = [0] == '-' = [1:]if == "" {return0, false } }varint64for := 0; < len(); ++ { := []if < '0' || > '9' {return0, false } = *10 + int64(-'0') }if { = - }return , true}
The pages are generated with Goldsv0.8.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.