Parameterize with timezones
This commit is contained in:
parent
37780cb323
commit
793717729a
123
docs/datetime.md
123
docs/datetime.md
@ -1,13 +1,20 @@
|
||||
# DateTime
|
||||
|
||||
Tomo has a builtin datatype for representing a specific single point in time:
|
||||
`DateTime`. A DateTime object is internally represented using a UNIX epoch in
|
||||
seconds and a number of nanoseconds to represent sub-second times (in C, the
|
||||
`DateTime`. A DateTime object is internally represented using a UNIX timestamp
|
||||
in seconds and a number of nanoseconds to represent sub-second times (in C, the
|
||||
equivalent of `struct timeval`). DateTime values do not represent calendar
|
||||
dates or clock times, they represent an exact moment in time, such as the
|
||||
moment when a file was last modified on the filesystem or the current moment
|
||||
(`DateTime.now()`).
|
||||
|
||||
⚠️⚠️⚠️ **WARNING** ⚠️⚠️⚠️ Dates and times are deeply counterintuitive and you should
|
||||
be extremely cautious when writing code that deals with dates and times. Effort
|
||||
has been made to ensure that Tomo's `DateTime` code uses standard libraries and
|
||||
is as correct as possible, but counterintuitive behaviors around time zones,
|
||||
daylight savings time, leap seconds, and other anomalous time situations can
|
||||
still cause bugs if you're not extremely careful.
|
||||
|
||||
## Time Zones
|
||||
|
||||
Because humans are not able to easily understand UNIX timestamps, the default
|
||||
@ -29,8 +36,12 @@ time. In that example, the initial time would be 3am March 1, 2023 in UTC, so
|
||||
one month later would be 3am April 1, 2023 in UTC, which is which is 11am March
|
||||
31st in local time. Most users would be unpleasantly surprised to find out that
|
||||
when it's February 28th in local time, one month later is March 28th until 8pm,
|
||||
at which point it becomes March 31st! For functions where this matters, there
|
||||
is an extra `local_time` argument that is `yes` by default.
|
||||
at which point it becomes March 31st!
|
||||
|
||||
For various functions where time zones matter, there is an optional `timezone`
|
||||
argument that, if set, will override the timezone when performing calculations.
|
||||
If unspecified, it is assumed that the current local timezone should be used.
|
||||
Time zones are specified by name, such as `America/New_York` or `EDT`.
|
||||
|
||||
## DateTime Methods
|
||||
|
||||
@ -46,24 +57,25 @@ example, one year from January 1, 2024 is January 1, 2025, which is 366 days
|
||||
later because 2024 is a leap year. Similarly, adding one month may add anywhere
|
||||
from 28 to 31 days, depending on the starting month. Days and weeks are
|
||||
affected by leap seconds. For this reason, `after()` takes an argument,
|
||||
`local_time` which is used to determine whether time offsets should be
|
||||
calculated using the current local time or UTC.
|
||||
`timezone` which is used to determine in which timezone the offsets should be
|
||||
calculated.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:after(seconds : Num = 0.0, minutes : Num = 0.0, hours : Num = 0.0, days : Int = 0, weeks : Int = 0, months : Int = 0, years : Int = 0, local_time : Bool = yes) -> DateTime
|
||||
datetime:after(seconds : Num = 0.0, minutes : Num = 0.0, hours : Num = 0.0, days : Int = 0, weeks : Int = 0, months : Int = 0, years : Int = 0, timezone : Text? = !Text) -> DateTime
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `seconds`: An amount of seconds to offset the datetime (default: 0).
|
||||
- `minutes`: An amount of minutes to offset the datetime (default: 0).
|
||||
- `hours`: An amount of hours to offset the datetime (default: 0).
|
||||
- `days`: An amount of days to offset the datetime (default: 0).
|
||||
- `weeks`: An amount of weeks to offset the datetime (default: 0).
|
||||
- `months`: An amount of months to offset the datetime (default: 0).
|
||||
- `years`: An amount of years to offset the datetime (default: 0).
|
||||
- `local_time`: Whether to perform the calculations in local time (default: `yes`) or, if not, in UTC time.
|
||||
- `seconds` (optional): An amount of seconds to offset the datetime (default: 0).
|
||||
- `minutes` (optional): An amount of minutes to offset the datetime (default: 0).
|
||||
- `hours` (optional): An amount of hours to offset the datetime (default: 0).
|
||||
- `days` (optional): An amount of days to offset the datetime (default: 0).
|
||||
- `weeks` (optional): An amount of weeks to offset the datetime (default: 0).
|
||||
- `months` (optional): An amount of months to offset the datetime (default: 0).
|
||||
- `years` (optional): An amount of years to offset the datetime (default: 0).
|
||||
- `timezone` (optional): If specified, perform perform the calculations in the
|
||||
given timezone. If unspecified, the current local timezone will be used.
|
||||
|
||||
**Returns:**
|
||||
A new `DateTime` offset by the given amount.
|
||||
@ -84,12 +96,12 @@ specifier, which gives the date in `YYYY-MM-DD` form.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:date(local_time : Bool = yes) -> Text
|
||||
datetime:date(timezone : Text? = !Text) -> Text
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `local_time`: Whether to use local time (default: `yes`) or UTC.
|
||||
- `timezone` (optional): If specified, give the date in the given timezone (otherwise, use the current local timezone).
|
||||
|
||||
**Returns:**
|
||||
The date in `YYYY-MM-DD` format.
|
||||
@ -107,17 +119,18 @@ The date in `YYYY-MM-DD` format.
|
||||
**Description:**
|
||||
Using the C-style [`strftime`](https://linux.die.net/man/3/strftime) format
|
||||
options, return a text representation of the given date in the given format. If
|
||||
`local_time` is `no`, then use UTC instead of the current locale's timezone.
|
||||
`timezone` is specified, use that timezone instead of the current local
|
||||
timezone.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:format(format: Text = "%Y-%m-%dT%H:%M:%S%z", local_time : Bool = yes) -> Text
|
||||
datetime:format(format: Text = "%Y-%m-%dT%H:%M:%S%z", timezone : Text? = !Text) -> Text
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `format`: The `strftime` format to use (default: `"%Y-%m-%dT%H:%M:%S%z"`).
|
||||
- `local_time`: Whether to use local time (default: `yes`) or UTC.
|
||||
- `timezone` (optional): If specified, use the given timezone (otherwise, use the current local timezone).
|
||||
|
||||
**Returns:**
|
||||
Nothing.
|
||||
@ -165,7 +178,7 @@ provided optional fields.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:get(year : &Int? = !&Int, month : &Int? = !&Int, day : &Int? = !&Int, hour : &Int? = !&Int, minute : &Int? = !&Int, second : &Int? = !&Int, nanosecond : &Int? = !&Int, weekday : &Int? = !&Int, local_time=yes) -> Void
|
||||
datetime:get(year : &Int? = !&Int, month : &Int? = !&Int, day : &Int? = !&Int, hour : &Int? = !&Int, minute : &Int? = !&Int, second : &Int? = !&Int, nanosecond : &Int? = !&Int, weekday : &Int? = !&Int, timezone : Text? = !Text) -> Void
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
@ -178,7 +191,7 @@ datetime:get(year : &Int? = !&Int, month : &Int? = !&Int, day : &Int? = !&Int, h
|
||||
- `second`: If non-null, store the second of the minute here (0-59).
|
||||
- `nanosecond`: If non-null, store the nanosecond of the second here (0-1,000,000,000).
|
||||
- `weekday`: If non-null, store the day of the week here (sunday=1, saturday=7)
|
||||
- `local_time`: Whether to use the local timezone (default: `yes`) or UTC.
|
||||
- `timezone` (optional): If specified, give values in the given timezone (otherwise, use the current local timezone).
|
||||
|
||||
**Returns:**
|
||||
Nothing.
|
||||
@ -194,6 +207,33 @@ dt:get(month=&month)
|
||||
|
||||
---
|
||||
|
||||
### `get_local_timezone`
|
||||
|
||||
**Description:**
|
||||
Get the local timezone's name (e.g. `America/New_York` or `UTC`. By default,
|
||||
this value is read from `/etc/localtime`, however, this can be overridden by
|
||||
calling `DateTime.set_local_timezone(...)`.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
DateTime.get_local_timezone() -> Text
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
None.
|
||||
|
||||
**Returns:**
|
||||
The name of the current local timezone.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
>> DateTime.get_local_timezone()
|
||||
= "America/New_York"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `hours_till`
|
||||
|
||||
**Description:**
|
||||
@ -353,13 +393,14 @@ between two `DateTime`s. For example: `5 minutes ago` or `1 day later`
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:relative(relative_to : DateTime = DateTime.now(), local_time : Bool = yes) -> Text
|
||||
datetime:relative(relative_to : DateTime = DateTime.now(), timezone : Text? = !Text) -> Text
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `relative_to` (optional): The time against which the relative time is calculated (default: `DateTime.now()`).
|
||||
- `local_time` (optional): Whether or not to perform calculations in local time (default: `yes`).
|
||||
- `timezone` (optional): If specified, perform calculations in the given
|
||||
timezone (otherwise, use the current local timezone).
|
||||
|
||||
**Returns:**
|
||||
Return a plain English textual representation of the approximate time
|
||||
@ -406,6 +447,36 @@ the_future := now():after(seconds=1)
|
||||
|
||||
---
|
||||
|
||||
### `set_local_timezone`
|
||||
|
||||
**Description:**
|
||||
Set the current local timezone to a given value by name (e.g.
|
||||
`America/New_York` or `UTC`). The local timezone is used as the default
|
||||
timezone for performing calculations and constructing `DateTime` objects from
|
||||
component parts. It's also used as the default way that `DateTime` objects are
|
||||
converted to text.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
DateTime.set_local_timezone(timezone : Text? = !Text) -> Void
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `timezone` (optional): if specified, set the current local timezone to the
|
||||
timezone with the given name. If null, reset the current local timezone to
|
||||
the system default (the value referenced in `/etc/localtime`).
|
||||
|
||||
**Returns:**
|
||||
Nothing.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
DateTime.set_local_timezone("America/Los_Angeles")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `time`
|
||||
|
||||
**Description:**
|
||||
@ -413,14 +484,14 @@ Return a text representation of the time component of the given datetime.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:time(seconds : Bool = no, am_pm : Bool = yes, local_time : Bool = yes) -> Text
|
||||
datetime:time(seconds : Bool = no, am_pm : Bool = yes, timezone : Text? = !Text) -> Text
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `seconds`: Whether to include seconds in the time (default: `no`).
|
||||
- `am_pm`: Whether to use am/pm in the representation or use a 24-hour clock (default: `yes`).
|
||||
- `local_time`: Whether to use local time (default: `yes`) or UTC.
|
||||
- `timezone` (optional): If specified, give the time in the given timezone (otherwise, use the current local timezone).
|
||||
|
||||
**Returns:**
|
||||
A text representation of the time component of the datetime.
|
||||
|
@ -265,18 +265,20 @@ env_t *new_compilation_unit(CORD libname)
|
||||
// Used as a default for functions below:
|
||||
{"now", "DateTime$now", "func()->DateTime"},
|
||||
|
||||
{"after", "DateTime$after", "func(dt:DateTime,seconds=0.0,minutes=0.0,hours=0.0,days=0,weeks=0,months=0,years=0,local_time=yes)->DateTime"},
|
||||
{"date", "DateTime$date", "func(dt:DateTime,local_time=yes)->Text"},
|
||||
{"format", "DateTime$format", "func(dt:DateTime,format=\"%Y-%m-%dT%H:%M:%S%z\",local_time=yes)->Text"},
|
||||
{"after", "DateTime$after", "func(dt:DateTime,seconds=0.0,minutes=0.0,hours=0.0,days=0,weeks=0,months=0,years=0,timezone=!Text)->DateTime"},
|
||||
{"date", "DateTime$date", "func(dt:DateTime,timezone=!Text)->Text"},
|
||||
{"format", "DateTime$format", "func(dt:DateTime,format=\"%Y-%m-%dT%H:%M:%S%z\",timezone=!Text)->Text"},
|
||||
{"from_unix_timestamp", "DateTime$from_unix_timestamp", "func(timestamp:Int64)->DateTime"},
|
||||
{"get", "DateTime$get", "func(dt:DateTime,year=!&Int,month=!&Int,day=!&Int,hour=!&Int,minute=!&Int,second=!&Int,nanosecond=!&Int,weekday=!&Int, local_time=yes)"},
|
||||
{"get", "DateTime$get", "func(dt:DateTime,year=!&Int,month=!&Int,day=!&Int,hour=!&Int,minute=!&Int,second=!&Int,nanosecond=!&Int,weekday=!&Int, timezone=!Text)"},
|
||||
{"get_local_timezone", "DateTime$get_local_timezone", "func()->Text"},
|
||||
{"hours_till", "DateTime$hours_till", "func(now:DateTime,then:DateTime)->Num"},
|
||||
{"minutes_till", "DateTime$minutes_till", "func(now:DateTime,then:DateTime)->Num"},
|
||||
{"new", "DateTime$new", "func(year:Int,month:Int,day:Int,hour=0,minute=0,second=0.0)->DateTime"},
|
||||
{"new", "DateTime$new", "func(year:Int,month:Int,day:Int,hour=0,minute=0,second=0.0,timezone=!Text)->DateTime"},
|
||||
{"parse", "DateTime$parse", "func(text:Text, format=\"%Y-%m-%dT%H:%M:%S%z\")->DateTime?"},
|
||||
{"relative", "DateTime$relative", "func(dt:DateTime,relative_to=DateTime.now(),local_time=yes)->Text"},
|
||||
{"relative", "DateTime$relative", "func(dt:DateTime,relative_to=DateTime.now(),timezone=!Text)->Text"},
|
||||
{"seconds_till", "DateTime$seconds_till", "func(now:DateTime,then:DateTime)->Num"},
|
||||
{"time", "DateTime$time", "func(dt:DateTime,seconds=no,am_pm=yes,local_time=yes)->Text"},
|
||||
{"set_local_timezone", "DateTime$set_local_timezone", "func(timezone=!Text)"},
|
||||
{"time", "DateTime$time", "func(dt:DateTime,seconds=no,am_pm=yes,timezone=!Text)->Text"},
|
||||
{"unix_timestamp", "DateTime$unix_timestamp", "func(dt:DateTime)->Int64"},
|
||||
)},
|
||||
{"Path", Type(TextType, .lang="Path", .env=namespace_env(env, "Path")), "Text_t", "Text$info", TypedArray(ns_entry_t,
|
||||
|
@ -4,14 +4,18 @@
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "datetime.h"
|
||||
#include "optionals.h"
|
||||
#include "patterns.h"
|
||||
#include "stdlib.h"
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
|
||||
static OptionalText_t _local_timezone = NULL_TEXT;
|
||||
|
||||
public Text_t DateTime$as_text(const DateTime_t *dt, bool colorize, const TypeInfo *type)
|
||||
{
|
||||
(void)type;
|
||||
@ -44,8 +48,10 @@ public DateTime_t DateTime$now(void)
|
||||
return (DateTime_t){.tv_sec=ts.tv_sec, .tv_usec=ts.tv_nsec};
|
||||
}
|
||||
|
||||
public DateTime_t DateTime$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second)
|
||||
public DateTime_t DateTime$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second, OptionalText_t timezone)
|
||||
{
|
||||
if (timezone.length >= 0)
|
||||
DateTime$set_local_timezone(timezone);
|
||||
struct tm info = {
|
||||
.tm_min=Int_to_Int32(minute, false),
|
||||
.tm_hour=Int_to_Int32(hour, false),
|
||||
@ -55,19 +61,26 @@ public DateTime_t DateTime$new(Int_t year, Int_t month, Int_t day, Int_t hour, I
|
||||
.tm_isdst=-1,
|
||||
};
|
||||
time_t t = mktime(&info);
|
||||
if (timezone.length >= 0)
|
||||
DateTime$set_local_timezone(_local_timezone);
|
||||
return (DateTime_t){.tv_sec=t + (time_t)second, .tv_usec=(suseconds_t)(fmod(second, 1.0) * 1e9)};
|
||||
}
|
||||
|
||||
public DateTime_t DateTime$after(DateTime_t dt, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, bool local_time)
|
||||
public DateTime_t DateTime$after(DateTime_t dt, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, OptionalText_t timezone)
|
||||
{
|
||||
double offset = seconds + 60.*minutes + 3600.*hours;
|
||||
dt.tv_sec += (time_t)offset;
|
||||
|
||||
struct tm info = {};
|
||||
if (local_time)
|
||||
if (timezone.length >= 0) {
|
||||
OptionalText_t old_timezone = _local_timezone;
|
||||
DateTime$set_local_timezone(timezone);
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
else
|
||||
gmtime_r(&dt.tv_sec, &info);
|
||||
DateTime$set_local_timezone(old_timezone);
|
||||
} else {
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
}
|
||||
|
||||
info.tm_mday += Int_to_Int32(days, false) + 7*Int_to_Int32(weeks, false);
|
||||
info.tm_mon += Int_to_Int32(months, false);
|
||||
info.tm_year += Int_to_Int32(years, false);
|
||||
@ -96,13 +109,18 @@ CONSTFUNC public double DateTime$hours_till(DateTime_t now, DateTime_t then)
|
||||
|
||||
public void DateTime$get(
|
||||
DateTime_t dt, Int_t *year, Int_t *month, Int_t *day, Int_t *hour, Int_t *minute, Int_t *second,
|
||||
Int_t *nanosecond, Int_t *weekday, bool local_time)
|
||||
Int_t *nanosecond, Int_t *weekday, OptionalText_t timezone)
|
||||
{
|
||||
struct tm info = {};
|
||||
if (local_time)
|
||||
|
||||
if (timezone.length >= 0) {
|
||||
OptionalText_t old_timezone = _local_timezone;
|
||||
DateTime$set_local_timezone(timezone);
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
else
|
||||
gmtime_r(&dt.tv_sec, &info);
|
||||
DateTime$set_local_timezone(old_timezone);
|
||||
} else {
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
}
|
||||
|
||||
if (year) *year = I(info.tm_year + 1900);
|
||||
if (month) *month = I(info.tm_mon + 1);
|
||||
@ -114,27 +132,34 @@ public void DateTime$get(
|
||||
if (weekday) *weekday = I(info.tm_wday + 1);
|
||||
}
|
||||
|
||||
public Text_t DateTime$format(DateTime_t dt, Text_t fmt, bool local_time)
|
||||
public Text_t DateTime$format(DateTime_t dt, Text_t fmt, OptionalText_t timezone)
|
||||
{
|
||||
struct tm info;
|
||||
struct tm *final_info = local_time ? localtime_r(&dt.tv_sec, &info) : gmtime_r(&dt.tv_sec, &info);
|
||||
if (timezone.length >= 0) {
|
||||
OptionalText_t old_timezone = _local_timezone;
|
||||
DateTime$set_local_timezone(timezone);
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
DateTime$set_local_timezone(old_timezone);
|
||||
} else {
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
}
|
||||
static char buf[256];
|
||||
size_t len = strftime(buf, sizeof(buf), Text$as_c_string(fmt), final_info);
|
||||
size_t len = strftime(buf, sizeof(buf), Text$as_c_string(fmt), &info);
|
||||
return Text$format("%.*s", (int)len, buf);
|
||||
}
|
||||
|
||||
public Text_t DateTime$date(DateTime_t dt, bool local_time)
|
||||
public Text_t DateTime$date(DateTime_t dt, OptionalText_t timezone)
|
||||
{
|
||||
return DateTime$format(dt, Text("%F"), local_time);
|
||||
return DateTime$format(dt, Text("%F"), timezone);
|
||||
}
|
||||
|
||||
public Text_t DateTime$time(DateTime_t dt, bool seconds, bool am_pm, bool local_time)
|
||||
public Text_t DateTime$time(DateTime_t dt, bool seconds, bool am_pm, OptionalText_t timezone)
|
||||
{
|
||||
Text_t text;
|
||||
if (seconds)
|
||||
text = DateTime$format(dt, am_pm ? Text("%l:%M:%S%P") : Text("%T"), local_time);
|
||||
text = DateTime$format(dt, am_pm ? Text("%l:%M:%S%P") : Text("%T"), timezone);
|
||||
else
|
||||
text = DateTime$format(dt, am_pm ? Text("%l:%M%P") : Text("%H:%M"), local_time);
|
||||
text = DateTime$format(dt, am_pm ? Text("%l:%M%P") : Text("%H:%M"), timezone);
|
||||
return Text$trim(text, Pattern(" "), true, true);
|
||||
}
|
||||
|
||||
@ -162,19 +187,21 @@ static inline Text_t num_format(long n, const char *unit)
|
||||
return Text$format((n == 1 || n == -1) ? "%ld %s %s" : "%ld %ss %s", n < 0 ? -n : n, unit, n < 0 ? "ago" : "later");
|
||||
}
|
||||
|
||||
public Text_t DateTime$relative(DateTime_t dt, DateTime_t relative_to, bool local_time)
|
||||
public Text_t DateTime$relative(DateTime_t dt, DateTime_t relative_to, OptionalText_t timezone)
|
||||
{
|
||||
struct tm info = {};
|
||||
if (local_time)
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
else
|
||||
gmtime_r(&dt.tv_sec, &info);
|
||||
|
||||
struct tm relative_info = {};
|
||||
if (local_time)
|
||||
|
||||
if (timezone.length >= 0) {
|
||||
OptionalText_t old_timezone = _local_timezone;
|
||||
DateTime$set_local_timezone(timezone);
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
localtime_r(&relative_to.tv_sec, &relative_info);
|
||||
else
|
||||
gmtime_r(&relative_to.tv_sec, &relative_info);
|
||||
DateTime$set_local_timezone(old_timezone);
|
||||
} else {
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
localtime_r(&relative_to.tv_sec, &relative_info);
|
||||
}
|
||||
|
||||
double second_diff = DateTime$seconds_till(relative_to, dt);
|
||||
if (info.tm_year != relative_info.tm_year && fabs(second_diff) > 365.*24.*60.*60.)
|
||||
@ -209,6 +236,34 @@ CONSTFUNC public DateTime_t DateTime$from_unix_timestamp(Int64_t timestamp)
|
||||
return (DateTime_t){.tv_sec=(time_t)timestamp};
|
||||
}
|
||||
|
||||
public void DateTime$set_local_timezone(OptionalText_t timezone)
|
||||
{
|
||||
if (timezone.length >= 0) {
|
||||
setenv("TZ", Text$as_c_string(timezone), 1);
|
||||
} else {
|
||||
unsetenv("TZ");
|
||||
}
|
||||
_local_timezone = timezone;
|
||||
tzset();
|
||||
}
|
||||
|
||||
public Text_t DateTime$get_local_timezone(void)
|
||||
{
|
||||
if (_local_timezone.length < 0) {
|
||||
static char buf[PATH_MAX];
|
||||
ssize_t len = readlink("/etc/localtime", buf, sizeof(buf));
|
||||
if (len < 0)
|
||||
fail("Could not get local timezone!");
|
||||
|
||||
char *zoneinfo = strstr(buf, "/zoneinfo/");
|
||||
if (zoneinfo)
|
||||
_local_timezone = Text$from_str(zoneinfo + strlen("/zoneinfo/"));
|
||||
else
|
||||
fail("Could not resolve local timezone!");
|
||||
}
|
||||
return _local_timezone;
|
||||
}
|
||||
|
||||
public const TypeInfo DateTime$info = {
|
||||
.size=sizeof(DateTime_t),
|
||||
.align=__alignof__(DateTime_t),
|
||||
|
@ -6,25 +6,28 @@
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "integers.h"
|
||||
#include "optionals.h"
|
||||
#include "types.h"
|
||||
#include "util.h"
|
||||
|
||||
Text_t DateTime$as_text(const DateTime_t *dt, bool colorize, const TypeInfo *type);
|
||||
PUREFUNC int32_t DateTime$compare(const DateTime_t *a, const DateTime_t *b, const TypeInfo *type);
|
||||
DateTime_t DateTime$now(void);
|
||||
DateTime_t DateTime$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second);
|
||||
DateTime_t DateTime$after(DateTime_t dt, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, bool local_time);
|
||||
DateTime_t DateTime$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second, OptionalText_t timezone);
|
||||
DateTime_t DateTime$after(DateTime_t dt, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, OptionalText_t timezone);
|
||||
CONSTFUNC double DateTime$seconds_till(DateTime_t now, DateTime_t then);
|
||||
CONSTFUNC double DateTime$minutes_till(DateTime_t now, DateTime_t then);
|
||||
CONSTFUNC double DateTime$hours_till(DateTime_t now, DateTime_t then);
|
||||
void DateTime$get(DateTime_t dt, Int_t *year, Int_t *month, Int_t *day, Int_t *hour, Int_t *minute, Int_t *second, Int_t *nanosecond, Int_t *weekday, bool local_time);
|
||||
Text_t DateTime$format(DateTime_t dt, Text_t fmt, bool local_time);
|
||||
Text_t DateTime$date(DateTime_t dt, bool local_time);
|
||||
Text_t DateTime$time(DateTime_t dt, bool seconds, bool am_pm, bool local_time);
|
||||
void DateTime$get(DateTime_t dt, Int_t *year, Int_t *month, Int_t *day, Int_t *hour, Int_t *minute, Int_t *second, Int_t *nanosecond, Int_t *weekday, OptionalText_t timezone);
|
||||
Text_t DateTime$format(DateTime_t dt, Text_t fmt, OptionalText_t timezone);
|
||||
Text_t DateTime$date(DateTime_t dt, OptionalText_t timezone);
|
||||
Text_t DateTime$time(DateTime_t dt, bool seconds, bool am_pm, OptionalText_t timezone);
|
||||
OptionalDateTime_t DateTime$parse(Text_t text, Text_t format);
|
||||
Text_t DateTime$relative(DateTime_t dt, DateTime_t relative_to, bool local_time);
|
||||
Text_t DateTime$relative(DateTime_t dt, DateTime_t relative_to, OptionalText_t timezone);
|
||||
CONSTFUNC Int64_t DateTime$unix_timestamp(DateTime_t dt);
|
||||
CONSTFUNC DateTime_t DateTime$from_unix_timestamp(Int64_t timestamp);
|
||||
void DateTime$set_local_timezone(OptionalText_t timezone);
|
||||
Text_t DateTime$get_local_timezone(void);
|
||||
|
||||
extern const TypeInfo DateTime$info;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user