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. proto method from-posix(|) { * }
  12. multi method from-posix($posix) {
  13. nqp::create(Instant).SET-SELF(
  14. Rakudo::Internals.tai-from-posix($posix,0).Rat
  15. )
  16. }
  17. multi method from-posix($posix, Bool $prefer-leap-second) {
  18. # $posix is in general not expected to be an integer.
  19. # If $prefer-leap-second is true, 915148800 is interpreted to
  20. # mean 1998-12-31T23:59:60Z rather than 1999-01-01T00:00:00Z.
  21. nqp::create(Instant).SET-SELF(
  22. Rakudo::Internals.tai-from-posix($posix,$prefer-leap-second).Rat
  23. )
  24. }
  25. method to-posix() {
  26. # The inverse of .from-posix, except that the second return
  27. # value is true if *and only if* this Instant is in a leap
  28. # second.
  29. Rakudo::Internals.posix-from-tai($!tai)
  30. }
  31. multi method Str(Instant:D:) {
  32. 'Instant:' ~ $!tai
  33. }
  34. multi method perl(Instant:D:) {
  35. "Instant.from-posix{self.to-posix.perl}";
  36. }
  37. method Bridge(Instant:D:) { $!tai.Bridge }
  38. method Num (Instant:D:) { $!tai.Num }
  39. method Rat (Instant:D:) { $!tai }
  40. method Int (Instant:D:) { $!tai.Int }
  41. method narrow(Instant:D:) { $!tai.narrow }
  42. method Date(Instant:D:) { Date.new(self) }
  43. method DateTime(Instant:D:) { DateTime.new(self) }
  44. # TODO: should be the new .gist, probably
  45. # method Str() {
  46. # 'Instant:' ~ default-formatter
  47. # ::DateTime.new(self), :subseconds
  48. # }
  49. }
  50. multi sub infix:«cmp»(Instant:D $a, Instant:D $b) {
  51. $a.tai <=> $b.tai }
  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, Instant:D $b) {
  68. $a.tai <= $b.tai
  69. }
  70. multi sub infix:«>=»(Instant:D $a, Instant:D $b) {
  71. $a.tai >= $b.tai
  72. }
  73. multi sub infix:<+>(Instant:D $a, Real:D $b) {
  74. nqp::create(Instant).SET-SELF($a.tai + $b.Rat)
  75. }
  76. multi sub infix:<+>(Real:D $a, Instant:D $b) {
  77. nqp::create(Instant).SET-SELF($a.Rat + $b.tai)
  78. }
  79. multi sub infix:<+>(Instant:D $a, Duration:D $b) {
  80. nqp::create(Instant).SET-SELF($a.tai + $b.tai)
  81. }
  82. multi sub infix:<+>(Duration:D $a, Instant:D $b) {
  83. nqp::create(Instant).SET-SELF($a.tai + $b.tai)
  84. }
  85. multi sub infix:<->(Instant:D $a, Instant:D $b) {
  86. Duration.new: $a.tai - $b.tai;
  87. }
  88. multi sub infix:<->(Instant:D $a, Real:D $b) {
  89. nqp::create(Instant).SET-SELF($a.tai - $b.Rat)
  90. }
  91. sub term:<time>() { nqp::p6box_i(nqp::time_i()) }
  92. sub term:<now>() {
  93. # FIXME: During a leap second, the returned value is one
  94. # second greater than it should be.
  95. nqp::create(Instant).SET-SELF(
  96. Rakudo::Internals.tai-from-posix(nqp::time_n,0).Rat
  97. )
  98. }
  99. Rakudo::Internals.REGISTER-DYNAMIC: '$*INITTIME', {
  100. PROCESS::<$INITTIME> := nqp::create(Instant).SET-SELF(
  101. Rakudo::Internals.tai-from-posix(Rakudo::Internals.INITTIME,0).Rat
  102. )
  103. }