/
Instant.pm
119 lines (100 loc) · 2.99 KB
/
Instant.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
my class Duration {... }
my class Instant is Cool does Real {
has Rat $.x;
# A linear count of seconds since 1970-01-01T00:00:00Z, plus
# tai-utc::initial-offset. Thus, $.x matches TAI from 1970
# to the present.
method new($x) { self.bless: x => $x.Rat }
method from-posix($posix, Bool $prefer-leap-second = False) {
# $posix is in general not expected to be an integer.
# If $prefer-leap-second is true, 915148800 is interpreted to
# mean 1998-12-31T23:59:60Z rather than 1999-01-01T00:00:00Z.
my $p = floor $posix;
my $offset = tai-utc::initial-offset;
for tai-utc::leap-second-posix() {
if $_ < $p {
++$offset;
} else {
return self.new: $posix + $offset + do
$_ == $p && !$prefer-leap-second
}
}
self.new: $posix + $offset;
}
method to-posix() {
# The inverse of .from-posix, except that the second return
# value is true if *and only if* this Instant is in a leap
# second.
my $n = floor $.x;
my $offset = tai-utc::initial-offset;
for tai-utc::leap-second-posix() {
if $_ < $n - $offset {
++$offset;
} else {
return ($.x - $offset, $n - $offset == $_)
}
}
($.x - $offset, False)
}
multi method Str(Instant:D:) {
'Instant:' ~ $.x
}
multi method perl(Instant:D:) {
"Instant.new(x => $.x.perl())";
}
method Bridge(Instant:D:) { $.x.Bridge }
method Num (Instant:D:) { $.x.Num }
method Int (Instant:D:) { $.x.Int }
# TODO: should be the new .gist, probably
# method Str() {
# 'Instant:' ~ default-formatter
# ::DateTime.new(self), :subseconds
# }
}
multi sub infix:«cmp»(Instant:D $a, Instant:D $b) {
$a.x <=> $b.x
}
multi sub infix:«<=>»(Instant:D $a, Instant:D $b) {
$a.x <=> $b.x
}
multi sub infix:«==»(Instant:D $a, Instant:D $b) {
$a.x == $b.x
}
multi sub infix:«!=»(Instant:D $a, Instant:D $b) {
$a.x != $b.x
}
multi sub infix:«<»(Instant:D $a, Instant:D $b) {
$a.x < $b.x
}
multi sub infix:«>»(Instant:D $a, Instant:D $b) {
$a.x > $b.x
}
multi sub infix:«<=»(Instant:D $a, Instant:D $b) {
$a.x <= $b.x
}
multi sub infix:«>=»(Instant:D $a, Instant:D $b) {
$a.x >= $b.x
}
multi sub infix:<+>(Instant:D $a, Real:D $b) {
Instant.new: $a.x + $b;
}
multi sub infix:<+>(Real:D $a, Instant:D $b) {
Instant.new: $a + $b.x;
}
multi sub infix:<+>(Instant:D $a, Duration:D $b) {
Instant.new: $a.x + $b.x;
}
multi sub infix:<+>(Duration:D $a, Instant:D $b) {
Instant.new: $a.x + $b.x;
}
multi sub infix:<->(Instant:D $a, Instant:D $b) {
Duration.new: $a.x - $b.x;
}
multi sub infix:<->(Instant:D $a, Real:D $b) {
Instant.new: $a.x - $b;
}
sub term:<now>() {
# FIXME: During a leap second, the returned value is one
# second greater than it should be.
Instant.from-posix: nqp::time_n
}