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
120
121
122
123
124
125
126
127
128
|
package mainsa
import (
"errors"
"fmt"
"strings"
"time"
)
const (
sunoLen = 8 * time.Hour
linjaLen = sunosInLinja * sunoLen
sikeLen = linjasInSike * linjaLen
tawaLen = sikesInTawa * sikeLen
suliLen = tawasInSuli * tawaLen
)
const (
sunosInLinja = 3
linjasInSike = 3
sikesInTawa = 3
tawasInSuli = 4
sunosInSike = sunosInLinja * linjasInSike
sunosInTawa = sunosInSike * sikesInTawa
sunosInSuli = sunosInTawa * tawasInSuli
)
//go:generate go tool stringer -type=Tawa
// Tawa is a set of 3 cycles, or a season.
type Tawa int
// The four tawas of a year.
const (
Kasi Tawa = 1 + iota
Seli
Sin
Lete
)
//go:generate go tool stringer -type=Sike
// Sike is a set of 3 threads, or a month.
type Sike int
// The three sikes.
const (
Kama Sike = 1 + iota
Poka
Monsi
)
//go:generate go tool stringer -type=Nanpa
// Nanpa is a generic toki pona number
type Nanpa int
// Numbers
const (
Wan Nanpa = 1 + iota
Tu
Mute
)
// TenpoNimi is the name of a given time. The remainder time is given as a time.Duration and should be shown in hour:minute format using time constant "3:04".
type TenpoNimi struct {
Year int // suli
Season Tawa // tawa
Month Sike // sike
Week Nanpa // linja
Day Nanpa // suno
Remainder time.Duration
}
func awen(d time.Duration) string {
return fmt.Sprintf("%d:%02d", int(d.Hours()), int(d.Minutes())%60)
}
func (tn TenpoNimi) String() string {
return strings.ToLower(fmt.Sprintf(
"suli %d tawa %s sike %s linja %s suno %s awen %s",
tn.Year,
tn.Season,
tn.Month,
tn.Week,
tn.Day,
awen(tn.Remainder),
))
}
const zeroDateUnix = 1538870400
// YearZero is the arbitrary anchor date from plane 432 to ma Insa year 1 planting season, coming cycle, first week, first day..
var YearZero = time.Unix(zeroDateUnix, 0)
// Errors
var (
ErrBeforeEpoch = errors.New("mainsa: time before zero date")
)
// At returns the time in ma Insa for a given Go time.
func At(t time.Time) (TenpoNimi, error) {
if t.Before(YearZero) {
return TenpoNimi{}, ErrBeforeEpoch
}
dur := t.Sub(YearZero)
var linjas = int(dur / linjaLen) // week => 3 days
var sikes = int(dur / sikeLen) // month => 3 weeks
var tawas = int(dur / tawaLen) // season => 3 months
var sulis = int(dur / suliLen) // year => 4 seasons
sunosd := float64(dur) / float64(sunoLen)
sunos := int(sunosd)
rem := time.Duration((sunosd - float64(sunos)) * float64(sunoLen)).Round(time.Minute)
result := TenpoNimi{
Year: sulis,
Season: Tawa(tawas%tawasInSuli) + 1,
Month: Sike(sikes%sikesInTawa) + 1,
Week: Nanpa(linjas%linjasInSike) + 1,
Day: Nanpa(sunos%sunosInLinja) + 1,
Remainder: rem,
}
return result, nil
}
|