diff --git a/src/std/date.ab b/src/std/date.ab new file mode 100644 index 00000000..6d4d5ec3 --- /dev/null +++ b/src/std/date.ab @@ -0,0 +1,109 @@ +/// EXPERIMENTAL +/// Format a date with a special format +/// If no date is specified, the current date is used +/// If no format is specified, "%FT%T%Z" format is used +/// For more info about format type "man date" on your shell or go to https://www.gnu.org/software/coreutils/date +/// Format : +/// %% a literal % +/// %a locale's abbreviated weekday name (e.g., Sun) +/// %A locale's full weekday name (e.g., Sunday) +/// %b locale's abbreviated month name (e.g., Jan) +/// %B locale's full month name (e.g., January) +/// %c locale's date and time (e.g., Thu Mar 3 23:05:25 2005) +/// %C century; like %Y, except omit last two digits (e.g., 20) +/// %d day of month (e.g., 01) +/// %D date; same as %m/%d/%y +/// %e day of month, space padded; same as %_d +/// %F full date; like %+4Y-%m-%d +/// %g last two digits of year of ISO week number (see %G) +/// %G year of ISO week number (see %V); normally useful only with %V +/// %h same as %b +/// %H hour (00..23) +/// %I hour (01..12) +/// %j day of year (001..366) +/// %k hour, space padded ( 0..23); same as %_H +/// %l hour, space padded ( 1..12); same as %_I +/// %m month (01..12) +/// %M minute (00..59) +/// %n a newline +/// %N nanoseconds (000000000..999999999) +/// %p locale's equivalent of either AM or PM; blank if not known +/// %P like %p, but lower case +/// %q quarter of year (1..4) +/// %r locale's 12-hour clock time (e.g., 11:11:04 PM) +/// %R 24-hour hour and minute; same as %H:%M +/// %s seconds since the Epoch (1970-01-01 00:00 UTC) +/// %S second (00..60) +/// %t a tab +/// %T time; same as %H:%M:%S +/// %u day of week (1..7); 1 is Monday +/// %U week number of year, with Sunday as first day of week (00..53) +/// %V ISO week number, with Monday as first day of week (01..53) +/// %w day of week (0..6); 0 is Sunday +/// %W week number of year, with Monday as first day of week (00..53) +/// %x locale's date representation (e.g., 12/31/99) +/// %X locale's time representation (e.g., 23:13:48) +/// %y last two digits of year (00..99) +/// %Y year +/// %z +hhmm numeric time zone (e.g., -0400) +/// %:z +hh:mm numeric time zone (e.g., -04:00) +/// %::z +hh:mm:ss numeric time zone (e.g., -04:00:00) +/// %:::z numeric time zone with : to necessary precision (e.g., -04, +05:30) +/// %Z alphabetic time zone abbreviation (e.g., EDT) +/// +/// By default, date pads numeric fields with zeroes. The following optional flags may follow '%': +/// +/// - (hyphen) do not pad the field +/// _ (underscore) pad with spaces +/// 0 (zero) pad with zeros +/// + pad with zeros, and put '+' before future years with >4 digits +/// ^ use upper case if possible +/// # use opposite case if possible +pub fun date_posix(format: Text = "", date: Text = "", utc: Bool = false): Text { + if format == "": format = "%FT%T%Z" + if date == "": date = unsafe $date +"%FT%T%Z"$ + if (utc) { + return $date --utc -d "{date}" +"{format}"$? + } else { + return $date -d "{date}" +"{format}"$? + } +} + +/// Return current timestamp (seconds since the Epoch (1970-01-01 00:00 UTC)) +#[allow_absurd_cast] +pub fun now(): Num { + return unsafe $date +%s$ as Num +} + +/// EXPERIMENTAL +/// Add value to date. +/// If no date is specified, the current date is used +/// Ex : date_add("+3 days") +/// You can use : +/// (+/-) +/// years +/// months +/// days +/// hours +/// minutes +/// seconds +pub fun date_add(add:Text, date:Text = "", utc: Bool = false): Text { + if date == "": date = unsafe $date +"%FT%T%Z"$ + return date_posix("", "{date_posix("%F", date, utc)?} {add} {date_posix("%T", date, utc)?}", utc)? +} + +/// EXPERIMENTAL +// Compare 2 date +// Return 1 if date_a is after date_b +// Return 0 if date_a and date_b is the same +// Return -1 if date_b is after date_a +// If date_b is not provided, current date will be used +#[allow_absurd_cast] +pub fun date_compare(date_a: Text, date_b: Text = "", utc: Bool = false): Num { + if date_b == "": date_b = unsafe date_posix("", "", utc) + let timestamp_a = date_posix("%s", date_a, utc)? as Num + let timestamp_b = date_posix("%s", date_b, utc)? as Num + if timestamp_a > timestamp_b: return 1 + if timestamp_a == timestamp_b: return 0 + if timestamp_a < timestamp_b: return -1 +} \ No newline at end of file diff --git a/src/tests/stdlib/date_add.ab b/src/tests/stdlib/date_add.ab new file mode 100644 index 00000000..6c8404b1 --- /dev/null +++ b/src/tests/stdlib/date_add.ab @@ -0,0 +1,5 @@ +import * from "std/date" + +main { + if unsafe date_add("+17 Days", "2009-02-07T09:46:40UTC", true) == "2009-02-24T09:46:40UTC": echo "Succeded" +} \ No newline at end of file diff --git a/src/tests/stdlib/date_compare.ab b/src/tests/stdlib/date_compare.ab new file mode 100644 index 00000000..04bca715 --- /dev/null +++ b/src/tests/stdlib/date_compare.ab @@ -0,0 +1,5 @@ +import * from "std/date" + +main { + if (unsafe date_compare("2000-01-01") == -1 and unsafe date_compare("2100-01-01") == 1) : echo "Succeded" +} \ No newline at end of file diff --git a/src/tests/stdlib/date_posix.ab b/src/tests/stdlib/date_posix.ab new file mode 100644 index 00000000..1180f986 --- /dev/null +++ b/src/tests/stdlib/date_posix.ab @@ -0,0 +1,5 @@ +import * from "std/date" + +main { + if unsafe date_posix("", "@1234000000", true) == "2009-02-07T09:46:40UTC": echo "Succeded" +} \ No newline at end of file diff --git a/src/tests/stdlib/now.ab b/src/tests/stdlib/now.ab new file mode 100644 index 00000000..e37a550d --- /dev/null +++ b/src/tests/stdlib/now.ab @@ -0,0 +1,5 @@ +import * from "std/date" + +main { + if now() == (unsafe $date +%s$ as Num): echo "Succeded" +} \ No newline at end of file