Files
c3c/lib/std/time/datetime.c3
Christoffer Lerno 4c1edfb941 Dev (#777)
* The new @if directive.
2023-06-10 23:16:28 +02:00

175 lines
4.5 KiB
C

module std::time::datetime;
import libc;
fn DateTime now()
{
return from_time(time::now());
}
/**
* @require day >= 1 && day < 32
* @require hour >= 0 && hour < 24
* @require min >= 0 && min < 60
* @require sec >= 0 && sec < 60
* @require us >= 0 && us < 999_999
**/
fn DateTime from_date(int year, Month month = JANUARY, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0)
{
DateTime dt @noinit;
dt.set_date(year, month, day, hour, min, sec, us) @inline;
return dt;
}
fn TzDateTime DateTime.to_local(DateTime* this)
{
Tm tm @noinit;
Time_t time_t = (Time_t)this.time.to_seconds();
libc::localtime_r(&time_t, &tm);
TzDateTime dt;
dt.usec = (int)((long)this.time % (long)time::MICROSECONDS_PER_SECOND);
dt.sec = (char)tm.tm_sec;
dt.min = (char)tm.tm_min;
dt.hour = (char)tm.tm_hour;
dt.day = (char)tm.tm_mday;
dt.month = (Month)tm.tm_mon;
dt.year = tm.tm_year + 1900;
dt.weekday = !tm.tm_wday ? Weekday.SUNDAY : (Weekday)tm.tm_wday + 1;
dt.year_day = (ushort)tm.tm_yday;
dt.time = this.time;
$if $defined(tm.tm_gmtoff):
dt.gmt_offset = (int)tm.tm_gmtoff;
$else
$assert $defined(libc::_get_timezone);
CLong timezone;
libc::_get_timezone(&timezone);
dt.gmt_offset = (int)-timezone;
$endif
return dt;
}
/**
* @require day >= 1 && day < 32
* @require hour >= 0 && hour < 24
* @require min >= 0 && min <= 60
* @require sec >= 0 && sec < 60
* @require us >= 0 && us < 999_999
**/
fn void DateTime.set_date(DateTime *this, int year, Month month = JANUARY, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0)
{
Tm tm;
tm.tm_sec = sec;
tm.tm_min = min;
tm.tm_hour = hour;
tm.tm_mon = month.ordinal;
tm.tm_mday = day;
tm.tm_year = year - 1900;
Time_t time = libc::timegm(&tm);
this.set_time((Time)(time * (long)time::MICROSECONDS_PER_SECOND + us));
}
fn void DateTime.set_time(DateTime* this, Time time)
{
Tm tm @noinit;
Time_t time_t = (Time_t)time.to_seconds();
libc::gmtime_r(&time_t, &tm);
this.usec = (int)((long)time % (long)time::MICROSECONDS_PER_SECOND);
this.sec = (char)tm.tm_sec;
this.min = (char)tm.tm_min;
this.hour = (char)tm.tm_hour;
this.day = (char)tm.tm_mday;
this.month = (Month)tm.tm_mon;
this.year = tm.tm_year + 1900;
this.weekday = !tm.tm_wday ? Weekday.SUNDAY : (Weekday)tm.tm_wday + 1;
this.year_day = (ushort)tm.tm_yday;
this.time = time;
}
fn DateTime DateTime.add_seconds(DateTime* date, int seconds) => from_time(date.time.add_seconds(seconds));
fn DateTime DateTime.add_minutes(DateTime* date, int minutes) => from_time(date.time.add_minutes(minutes));
fn DateTime DateTime.add_hours(DateTime* date, int hours) => from_time(date.time.add_hours(hours));
fn DateTime DateTime.add_days(DateTime* date, int days) => from_time(date.time.add_days(days));
fn DateTime DateTime.add_weeks(DateTime* date, int weeks) => from_time(date.time.add_weeks(weeks));
fn DateTime DateTime.add_years(DateTime* date, int years)
{
if (!years) return *date;
return from_date(date.year + years, date.month, date.day, date.hour, date.min, date.sec, date.usec);
}
fn DateTime DateTime.add_months(DateTime* date, int months)
{
if (months == 0) return *date;
int year = date.year;
int month = date.month.ordinal;
switch
{
case months % 12 == 0:
year += months / 12;
case months < 0:
month += months % 12;
year += months / 12;
if (month < 0)
{
year--;
month += 12;
}
default:
month += months;
year += month / 12;
month %= 12;
}
return from_date(year, (Month)month, date.day, date.hour, date.min, date.sec, date.usec);
}
fn DateTime from_time(Time time)
{
DateTime dt @noinit;
dt.set_time(time) @inline;
return dt;
}
fn Time DateTime.to_time(DateTime* this) @inline
{
return this.time;
}
fn bool DateTime.after(DateTime* this, DateTime compare)
{
return this.time > compare.time;
}
fn bool DateTime.before(DateTime* this, DateTime compare)
{
return this.time < compare.time;
}
fn int DateTime.compare_to(DateTime* this, DateTime compare)
{
switch
{
case this.time > compare.time: return 1;
case this.time < compare.time: return -1;
default: return 0;
}
}
fn int DateTime.diff_years(DateTime *to, DateTime from)
{
int year_diff = to.year - from.year;
switch
{
case year_diff < 0: return -from.diff_years(*to);
case year_diff == 0: return 0;
}
if (to.year_day < from.year_day) year_diff--;
return year_diff;
}
fn double DateTime.diff_sec(DateTime to, DateTime from)
{
return (double)to.time.diff_us(from.time) / (double)time::MICROSECONDS_PER_SECOND;
}
fn TimeDuration DateTime.diff_us(DateTime to, DateTime from)
{
return to.time.diff_us(from.time);
}