Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add date function to stdlib #348

Merged
merged 8 commits into from
Jul 29, 2024
109 changes: 109 additions & 0 deletions src/std/date.ab
Original file line number Diff line number Diff line change
@@ -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
}
5 changes: 5 additions & 0 deletions src/tests/stdlib/date_add.ab
Original file line number Diff line number Diff line change
@@ -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"
}
5 changes: 5 additions & 0 deletions src/tests/stdlib/date_compare.ab
Original file line number Diff line number Diff line change
@@ -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"
}
5 changes: 5 additions & 0 deletions src/tests/stdlib/date_posix.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * from "std/date"

main {
if unsafe date_posix("", "@1234000000", true) == "2009-02-07T09:46:40UTC": echo "Succeded"
}
5 changes: 5 additions & 0 deletions src/tests/stdlib/now.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * from "std/date"

main {
if now() == (unsafe $date +%s$ as Num): echo "Succeded"
}
Loading