UXDate
UXDate holds a date and time as components (year, month, day, hour,
minute, second, microsecond) plus the time
zone those components are expressed in.
#use <UXKit> // or #import "UXDate.xc"Overview
Section titled “Overview”UXDate* d = UXDate.makeTime(2026, 9, 14, 16, 45, 7);
d.weekday(); // 1 = Mondayd.addingDays(1); // a new date, Tue 15 Sepd.addingMonths(5); // 2027-02-14UXDate.make(2026, 1, 1).daysUntil(d); // 256
UXDateFormatter.withPattern((u8*)"EEEE d MMMM yyyy").format(d);// Monday 14 September 2026Every derivation returns a new date; nothing mutates.
Integer arithmetic, and why it matters
Section titled “Integer arithmetic, and why it matters”Conversions go through a day number (days since 1970-01-01), computed with the exact integer civil-calendar algorithm.
No floating point is used, so the results are identical on every backend. A
date library built on seconds stored as a double gives slightly different
answers on a machine with a different FPU, and cannot run on a target with no
FPU. Here, 29 February 2024 is reached by counting.
UXDate.isLeapYear(2024); // true — divisible by 4UXDate.isLeapYear(1900); // false — divisible by 100UXDate.isLeapYear(2000); // true — divisible by 400All three rules apply: 28 Feb 2024 + 1 day is the 29th, and 28 Feb 2025 + 1 day is 1 March.
Month arithmetic clamps
Section titled “Month arithmetic clamps”UXDate.make(2026, 1, 31).addingMonths(1); // 2026-02-28, not 2026-03-03Adding a month to the 31st lands on the last day of the shorter month instead
of spilling into the next one. A calendar UI means this by “next month”, and
NSCalendar makes the same choice.
As a result, month arithmetic is not reversible: +1 month then
-1 month from 31 January gives 28 February then 28 January. Day arithmetic
is reversible, because a day is always a day.
Zones: components versus instant
Section titled “Zones: components versus instant”A UXDate’s components are a wall-clock reading, and zone says which
clock. inZone re-expresses the same instant on a different clock:
UXDate* here = UXDate.makeTime(2026, 9, 14, 16, 45, 0); // UTCUXDate* there = here.inZone(UXTimeZone.make((u8*)"PST", -480));
// here = 2026-09-14 16:45// there = 2026-09-14 08:45here.isSameInstant(there); // trueThe components differ but the moment is the same. When two dates come from
different zones, compare them with isSameInstant. Comparing
components would wrongly report them as different.
A date made without a zone is UTC, not local. A default of local time would
make the same code produce different data on different machines, which makes
timestamps in a shared file useless.
currentDateLocal gives the host’s clock when you want it.
Reading the clock
Section titled “Reading the clock”UXDate.currentDate(); // now, in UTCUXDate.currentDateLocal(); // now, in the host's zoneBoth go through the driver seam, so a backend with no clock still returns a date instead of failing. For anything you will compare or store, prefer UTC and convert for display.
Topics
Section titled “Topics”make · makeTime · makeMicro · currentDate · currentDateLocal · fromEpochSeconds · epochSeconds · setZone · inZone · isSameInstant · dayNumber · fromDayNumber · weekday · addingDays · addingWeeks · addingMonths · addingYears · addingHours · addingMinutes · addingSeconds · addingMicroseconds · daysUntil · daysInMonth · isLeapYear
static UXDate* make(i32 y, i32 mo, i32 d)A date at midnight. Month is 1–12 and day 1–31. Unlike C’s
struct tm, neither is zero-based.
makeTime
Section titled “makeTime”static UXDate* makeTime(i32 y, i32 mo, i32 d, i32 h, i32 mi, i32 s)makeMicro
Section titled “makeMicro”static UXDate* makeMicro(i32 y, i32 mo, i32 d, i32 h, i32 mi, i32 s, i32 us)Microseconds within the second, 0–999999. They let an event trace order
things that happened in the same second.
currentDate
Section titled “currentDate”static UXDate* currentDate(void)Now, in UTC, read through the driver.
currentDateLocal
Section titled “currentDateLocal”static UXDate* currentDateLocal(void)Now, in the host’s zone, with the host’s DST rules already applied. See
UXTimeZone.
fromEpochSeconds
Section titled “fromEpochSeconds”static UXDate* fromEpochSeconds(i32 secs, i32 us)From a Unix timestamp.
epochSeconds
Section titled “epochSeconds”i32 epochSeconds(void)The instant as a Unix timestamp, zone taken into account.
setZone
Section titled “setZone”void setZone(UXTimeZone* z)Sets which clock the existing components are on. This reinterprets the
components and does not convert them. Use inZone to convert.
inZone
Section titled “inZone”UXDate* inZone(UXTimeZone* tz)The same instant, expressed on another clock. See above.
zoneOffsetMinutes
Section titled “zoneOffsetMinutes”i32 zoneOffsetMinutes(void)This date’s offset from UTC, in minutes. It is 0 when the date has no zone,
the same answer UTC gives, so no null check is needed.
epochSeconds subtracts this value to get back to an absolute
instant. Print it alongside a timestamp when the zone matters.
UXTimeZone.offsetString is the
formatted form.
isSameInstant
Section titled “isSameInstant”bool isSameInstant(UXDate* other)Whether two dates are the same moment, whatever zones they are in.
dayNumber
Section titled “dayNumber”i32 dayNumber(void)Days since 1970-01-01. The calendar maths runs on this integer, and it is a cheap key for grouping by day.
fromDayNumber
Section titled “fromDayNumber”static UXDate* fromDayNumber(i32 z)The inverse of dayNumber.
weekday
Section titled “weekday”i32 weekday(void)0 = Sunday through 6 = Saturday. The formatter’s E uses this index.
addingDays
Section titled “addingDays”UXDate* addingDays(i32 n)Exact across month and year boundaries, and reversible. Negative values go back.
addingWeeks
Section titled “addingWeeks”UXDate* addingWeeks(i32 n)addingMonths
Section titled “addingMonths”UXDate* addingMonths(i32 n)Clamps the day to the target month’s length. See above.
addingYears
Section titled “addingYears”UXDate* addingYears(i32 n)29 February clamps to the 28th in a non-leap year, for the same reason.
addingHours
Section titled “addingHours”UXDate* addingHours(i32 n)addingMinutes
Section titled “addingMinutes”UXDate* addingMinutes(i32 n)addingSeconds
Section titled “addingSeconds”UXDate* addingSeconds(i32 n)Carries into the day, and from there into the month and year.
addingMicroseconds
Section titled “addingMicroseconds”UXDate* addingMicroseconds(i32 n)daysUntil
Section titled “daysUntil”i32 daysUntil(UXDate* other)Whole days between the two dates, by day number. The result is exact regardless
of the times of day, and negative when other is earlier.
daysInMonth
Section titled “daysInMonth”static i32 daysInMonth(i32 y, i32 mo)Leap years included. A month grid needs this.
isLeapYear
Section titled “isLeapYear”static bool isLeapYear(i32 y)Example
Section titled “Example”iso: 2026-09-14time: 16:45:07long: Monday 14 September 2026weekday index: 1+1 day: Tue 2026-09-15+5 months: 2027-02-1431 Jan +1m: 2026-02-28leap: 2024=1 2025=0 1900=0 2000=129 Feb 24: Thursday 29 February 202428 Feb 25: Saturday 1 March 2025days 2026-01-01 -> 2026-09-14: 256utc: 2026-09-14 16:45in PST: 2026-09-14 08:45same instant: 1The program is website/site/examples/uxkit/dates.xc; the doc-examples gate
compiles it, and the output above is what it prints.
Conforms to
Section titled “Conforms to”- A plain class (not an
Objectsubclass)
See also
Section titled “See also”UXDateFormatter: dates to stringsUXTimeZone: zones, and why they are fixed-offsetUXDatePicker: choosing a date in a window