1. my class Date { ... }
  2. my class DateTime { ... }
  3. my class Duration {... }
  4. my class Instant is Cool does Real {
  5. has Rat $.tai;
  6. # A linear count of seconds since 1970-01-01T00:00:00Z, plus
  7. # Rakudo::Internals.initial-offset. Thus, $.tai matches TAI from 1970
  8. # to the present.
  9. method SET-SELF($!tai) { self } # cannot be private because of operators
  10. method new(*@) { X::Cannot::New.new(class => self).throw }
  11. method from-posix($posix, Bool $prefer-leap-second = False) {
  12. # $posix is in general not expected to be an integer.
  13. # If $prefer-leap-second is true, 915148800 is interpreted to
  14. # mean 1998-12-31T23:59:60Z rather than 1999-01-01T00:00:00Z.
  15. nqp::create(Instant).SET-SELF(
  16. Rakudo::Internals.tai-from-posix($posix,$prefer-leap-second).Rat
  17. )
  18. }
  19. method to-posix() {
  20. # The inverse of .from-posix, except that the second return
  21. # value is true if *and only if* this Instant is in a leap
  22. # second.
  23. Rakudo::Internals.posix-from-tai($!tai)
  24. }
  25. multi method Str(Instant:D:) {
  26. 'Instant:' ~ $!tai
  27. }
  28. multi method perl(Instant:D:) {
  29. "Instant.from-posix{self.to-posix.perl}";
  30. }
  31. method Bridge(Instant:D:) { $!tai.Bridge }
  32. method Num (Instant:D:) { $!tai.Num }
  33. method Rat (Instant:D:) { $!tai }
  34. method Int (Instant:D:) { $!tai.Int }
  35. method narrow(Instant:D:) { $!tai.narrow }
  36. method Date(Instant:D:) { Date.new(self) }
  37. method DateTime(Instant:D: |c) { DateTime.new(self, |c) }
  38. # TODO: should be the new .gist, probably
  39. # method Str() {
  40. # 'Instant:' ~ default-formatter
  41. # ::DateTime.new(self), :subseconds
  42. # }
  43. }
  44. multi sub infix:«cmp»(Instant:D $a, Instant:D $b) {
  45. $a.tai <=> $b.tai }
  46. multi sub infix:«<=>»(Instant:D $a, Instant:D $b) {
  47. $a.tai <=> $b.tai
  48. }
  49. multi sub infix:«==»(Instant:D $a, Instant:D $b) {
  50. $a.tai == $b.tai
  51. }
  52. multi sub infix:«!=»(Instant:D $a, Instant:D $b) {
  53. $a.tai != $b.tai
  54. }
  55. multi sub infix:«<»(Instant:D $a, Instant:D $b) {
  56. $a.tai < $b.tai
  57. }
  58. multi sub infix:«>»(Instant:D $a, Instant:D $b) {
  59. $a.tai > $b.tai
  60. }
  61. multi sub infix:«<=»(Instant:D $a, Instant:D $b) {
  62. $a.tai <= $b.tai
  63. }
  64. multi sub infix:«>=»(Instant:D $a, Instant:D $b) {
  65. $a.tai >= $b.tai
  66. }
  67. multi sub infix:<+>(Instant:D $a, Real:D $b) {
  68. nqp::create(Instant).SET-SELF($a.tai + $b.Rat)
  69. }
  70. multi sub infix:<+>(Real:D $a, Instant:D $b) {
  71. nqp::create(Instant).SET-SELF($a.Rat + $b.tai)
  72. }
  73. multi sub infix:<+>(Instant:D $a, Duration:D $b) {
  74. nqp::create(Instant).SET-SELF($a.tai + $b.tai)
  75. }
  76. multi sub infix:<+>(Duration:D $a, Instant:D $b) {
  77. nqp::create(Instant).SET-SELF($a.tai + $b.tai)
  78. }
  79. multi sub infix:<->(Instant:D $a, Instant:D $b) {
  80. Duration.new: $a.tai - $b.tai;
  81. }
  82. multi sub infix:<->(Instant:D $a, Real:D $b) {
  83. nqp::create(Instant).SET-SELF($a.tai - $b.Rat)
  84. }
  85. sub term:<time>() { nqp::p6box_i(nqp::time_i()) }
  86. sub term:<now>() {
  87. # FIXME: During a leap second, the returned value is one
  88. # second greater than it should be.
  89. Instant.from-posix: nqp::time_n
  90. }
  91. Rakudo::Internals.REGISTER-DYNAMIC: '$*INITTIME', {
  92. PROCESS::<$INITTIME> := Instant.from-posix: Rakudo::Internals.INITTIME;
  93. }