@@ -2,15 +2,17 @@ local _ENV = mkmodule('datetime')
2
2
3
3
--[[
4
4
TODO: investigate applicability for adv mode.
5
- if advmode then TU_PER_DAY = 86400 ? or only for cur_year_tick?
5
+ if advmode then TICKS_PER_DAY = 86400 ? or only for cur_year_tick?
6
6
advmod_TU / 72 = ticks
7
7
--]]
8
8
9
- local TU_PER_DAY = 1200
10
- local TU_PER_MONTH = TU_PER_DAY * 28
11
- local TU_PER_YEAR = TU_PER_MONTH * 12
12
- local DAYS_IN_YEAR = 336
13
- local MONTHS_IN_YEAR = 12
9
+ -- are these locals better in DwarfCalendar?
10
+ local DAYS_PER_MONTH = 28
11
+ local DAYS_PER_YEAR = 336
12
+ local MONTHS_PER_YEAR = 12
13
+ local TICKS_PER_DAY = 1200
14
+ local TICKS_PER_MONTH = TICKS_PER_DAY * DAYS_PER_MONTH
15
+ local TICKS_PER_YEAR = TICKS_PER_MONTH * MONTHS_PER_YEAR
14
16
15
17
local MONTHS = {
16
18
' Granite' ,
@@ -27,110 +29,209 @@ local MONTHS = {
27
29
' Obsidian' ,
28
30
}
29
31
30
- -- Ordinal suffix rules found here: https://en.wikipedia.org/wiki/Ordinal_indicator
31
- local function getOrdinalSuffix (ordinal )
32
- if (ordinal < 0 ) then
33
- ordinal = math.abs (ordinal )
34
- end
32
+ DwarfCalendar = defclass (DwarfCalendar )
35
33
36
- local rem = (ordinal < 100 ) and (ordinal % 10 ) or (ordinal % 100 )
37
- -- rem can be between 11 and 13 only when ordinal is > 100
38
- if (ordinal >= 11 and ordinal <= 13 ) or (rem >= 11 and rem <= 13 ) then
39
- return ' th'
34
+ DwarfCalendar .ATTRS {
35
+ year = 0 ,
36
+ year_tick = 0 ,
37
+ }
38
+
39
+ function DwarfCalendar :init ()
40
+ self :normalize ()
41
+ end
42
+
43
+ function DwarfCalendar :addTicks (ticks )
44
+ self .year_tick = self .year_tick + ticks
45
+ self :normalize ()
46
+ end
47
+
48
+ function DwarfCalendar :addDays (days )
49
+ self .year_tick = self .year_tick + self .daysToTicks (days )
50
+ self :normalize ()
51
+ end
52
+
53
+ function DwarfCalendar :addMonths (months )
54
+ self .year_tick = self .year_tick + self .monthsToTicks (months )
55
+ self :normalize ()
56
+ end
57
+
58
+ function DwarfCalendar :addYears (years )
59
+ self .year = self .year + years
60
+ end
61
+
62
+ -- returns an integer pair: (year), (year tick count)
63
+ function DwarfCalendar :getYears ()
64
+ return self .year , self .year_tick
65
+ end
66
+
67
+ -- returns days since beginning of a year, starting from zero
68
+ function DwarfCalendar :ticksToDays ()
69
+ return self .year_tick // TICKS_PER_DAY
70
+ end
71
+
72
+ -- returns days since the beginning of a month, starting from zero
73
+ function DwarfCalendar :ticksToDayOfMonth ()
74
+ return self :ticksToDays () % DAYS_PER_MONTH
75
+ end
76
+
77
+ -- returns months since the beginning of a year, starting from zero
78
+ function DwarfCalendar :ticksToMonths ()
79
+ return self .year_tick // TICKS_PER_MONTH
80
+ end
81
+
82
+ -- returns ticks since the beginning of a day
83
+ function DwarfCalendar :getDayTicks ()
84
+ return self .year_tick % TICKS_PER_DAY
85
+ end
86
+
87
+ -- returns ticks since the beginning of a month
88
+ function DwarfCalendar :getMonthTicks ()
89
+ return self .year_tick % TICKS_PER_MONTH
90
+ end
91
+
92
+ function DwarfCalendar :normalize ()
93
+ if (self .year_tick > TICKS_PER_YEAR ) then
94
+ self .year = self .year + (self .year_tick // TICKS_PER_YEAR )
95
+ self .year_tick = self .year_tick % TICKS_PER_YEAR
96
+ elseif (self .year_tick < 0 ) then
97
+ -- going backwards in time, subtract year by at least one.
98
+ self .year = self .year - math.max (1 , math.abs (self .year_tick ) // TICKS_PER_YEAR )
99
+ self .year_tick = self .year_tick % TICKS_PER_YEAR
40
100
end
41
- -- modulo again to handle the case when ordinal is > 100
42
- return ({' st' , ' nd' , ' rd' })[rem % 10 ] or ' th'
43
101
end
44
102
45
- DateTime = defclass (DateTime )
103
+ function DwarfCalendar :__add (other )
104
+ if DEBUG then self :_debugOps (other ) end
105
+ -- normalize() handles adjustments to year and year_tick
106
+ return DwarfCalendar { year = (self .year + other .year ), year_tick = (self .year_tick + other .year_tick ) }
107
+ end
46
108
47
- DateTime .ATTRS {
48
- year = 0 ,
49
- year_tick = 0 ,
50
- }
109
+ function DwarfCalendar :__sub (other )
110
+ if DEBUG then self :_debugOps (other ) end
111
+ -- normalize() handles adjustments to year and year_tick
112
+ return DwarfCalendar { year = (self .year - other .year ) , year_tick = (self .year_tick - other .year_tick ) }
113
+ end
114
+
115
+ function DwarfCalendar :_debugOps (other )
116
+ print (' first: ' .. self .year ,self .year_tick )
117
+ print (' second: ' .. other .year ,other .year_tick )
118
+ end
51
119
52
- function DateTime :init (args )
53
- -- TODO: normalize args, if needed
120
+ -- utility functions
121
+ function DwarfCalendar .daysToTicks (days )
122
+ return days * TICKS_PER_DAY
54
123
end
55
124
56
- -- returns an integer pair: (date represented by days), (day tick count)
57
- function DateTime :getDateAsDays ()
58
- local d , dt = self :getDayOfYear ()
59
- return self .year * DAYS_IN_YEAR + d , dt
125
+ function DwarfCalendar .monthsToTicks (months )
126
+ return months * TICKS_PER_MONTH
60
127
end
61
128
62
- -- returns an integer pair: (day of month), (day tick count)
129
+ function DwarfCalendar .getMonthNames ()
130
+ return MONTHS
131
+ end
132
+
133
+
134
+ DateTime = defclass (DateTime , DwarfCalendar )
135
+
136
+ -- returns an integer pair: (day of month starting from 1), (day tick count)
63
137
function DateTime :getDayOfMonth ()
64
- local md = (self .year_tick % TU_PER_MONTH ) / TU_PER_DAY ) + 1
65
- -- fetch day tick count
66
- local _ , dt = self :getDayOfYear ()
67
- return md , dt
138
+ return self :ticksToDayOfMonth () + 1 , self :getDayTicks (self .year_tick )
68
139
end
69
140
70
141
-- returns a string in ordinal form (e.g. 1st, 12th, 22nd, 101st, 111th, 133rd)
71
142
function DateTime :getDayOfMonthWithSuffix ()
72
143
local d = self :getDayOfMonth ()
73
- return tostring (d ).. getOrdinalSuffix (d )
144
+ return tostring (d ).. self . getOrdinalSuffix (d )
74
145
end
75
146
76
- -- returns an integer pair: (current day of year), (day tick count)
147
+ -- returns an integer pair: (current day of year, from 1 ), (day tick count)
77
148
function DateTime :getDayOfYear ()
78
- local d = (self .year_tick // TU_PER_DAY ) + 1
79
- return d , self .year_tick - (TU_PER_DAY * d )
80
- end
81
-
82
- -- returns an integer pair: (date represented by months), (month tick count)
83
- function DateTime :getDateAsMonths ()
84
- local m , mt = self :getMonth ()
85
- return self .year * MONTHS_IN_YEAR + m , mt
149
+ return self :ticksToDays () + 1 , self :getDayTicks ()
86
150
end
87
151
88
- -- returns an integer pair: (current month of the year), (month tick count)
152
+ -- returns an integer pair: (current month of the year, from 1 ), (month tick count)
89
153
function DateTime :getMonth ()
90
- local m = (self .year_tick // TU_PER_MONTH ) + 1
91
- return m , self .year_tick - (TU_PER_MONTH * m )
154
+ return self :ticksToMonths () + 1 , self :getMonthTicks ()
92
155
end
93
156
94
157
-- returns a string of the current month of the year
95
158
function DateTime :getNameOfMonth ()
96
159
return MONTHS [self :getMonth ()] or error (" getMonth(): bad index?" )
97
160
end
98
161
99
- -- returns an integer pair: (year), (year tick count)
100
- function DateTime :getYears ()
101
- return self .year , self .year_tick
162
+ function DateTime :toDuration ()
163
+ return Duration { year = self .year , year_tick = self .year_tick }
102
164
end
103
165
104
166
function DateTime :__add (other )
105
167
if DEBUG then self :_debugOps (other ) end
106
- if self .year_tick + other .year_tick > TU_PER_YEAR then
107
- -- We add a year when year_tick delta is greater than a year.
108
- return DateTime { year = (self .year + other .year + 1 ) , year_tick = (self .year_tick + other .year_tick - TU_PER_YEAR ) }
109
- else
110
- return DateTime { year = (self .year + other .year ) , year_tick = (self .year_tick + other .year_tick ) }
111
- end
112
- -- NOT REACHED
168
+ -- normalize() handles adjustments to year and year_tick
169
+ return DateTime { year = (self .year + other .year ), year_tick = (self .year_tick + other .year_tick ) }
113
170
end
114
171
172
+ -- might make sense to return a Duration here
115
173
function DateTime :__sub (other )
116
174
if DEBUG then self :_debugOps (other ) end
117
- if self .year_tick < other .year_tick then
118
- -- We subtract a year when year_tick delta is less than a year.
119
- return DateTime { year = (self .year - other .year - 1 ) , year_tick = (TU_PER_YEAR + self .year_tick - other .year_tick ) }
120
- else
121
- return DateTime { year = (self .year - other .year ) , year_tick = (self .year_tick - other .year_tick ) }
122
- end
123
- -- NOT REACHED
124
- end
125
-
126
- function DateTime :_debugOps (other )
127
- print (self .year ,self .year_tick )
128
- print (other .year ,other .year_tick )
175
+ -- normalize() handles adjustments to year and year_tick
176
+ return DateTime { year = (self .year - other .year ) , year_tick = (self .year_tick - other .year_tick ) }
129
177
end
130
178
131
179
-- Static functions
132
180
function DateTime .now ()
133
181
return DateTime { year = df .global .cur_year , year_tick = df .global .cur_year_tick }
134
182
end
135
183
184
+ -- Ordinal suffix rules found here: https://en.wikipedia.org/wiki/Ordinal_indicator
185
+ function DateTime .getOrdinalSuffix (ordinal )
186
+ if (ordinal < 0 ) then
187
+ ordinal = math.abs (ordinal )
188
+ end
189
+
190
+ local rem = (ordinal < 100 ) and (ordinal % 10 ) or (ordinal % 100 )
191
+ -- rem can be between 11 and 13 only when ordinal is > 100
192
+ if (ordinal >= 11 and ordinal <= 13 ) or (rem >= 11 and rem <= 13 ) then
193
+ return ' th'
194
+ end
195
+ -- modulo again to handle the case when ordinal is > 100
196
+ return ({' st' , ' nd' , ' rd' })[rem % 10 ] or ' th'
197
+ end
198
+
199
+ Duration = defclass (Duration , DwarfCalendar )
200
+
201
+ -- returns ticks since year zero
202
+ function Duration :getTicks ()
203
+ return self .year * TICKS_PER_YEAR + self .year_tick
204
+ end
205
+
206
+ -- returns an integer pair: (days since year zero), (day tick count)
207
+ function Duration :getDays ()
208
+ return self .year * DAYS_PER_YEAR + self :ticksToDays (), self :getDayTicks ()
209
+ end
210
+
211
+ -- returns an integer pair: (months since year zero), (month tick count)
212
+ function Duration :getMonths ()
213
+ return self .year * MONTHS_PER_YEAR + self :ticksToMonths (), self :getMonthTicks ()
214
+ end
215
+
216
+ -- returns parts of an elapsed time:
217
+ -- years,
218
+ -- months, - since start of year
219
+ -- days, - since start of month
220
+ -- day tick count - since start of day
221
+ function Duration :getYearsMonthsDays ()
222
+ return self .year , self :ticksToMonths (), self :ticksToDayOfMonth (), self :getDayTicks ()
223
+ end
224
+
225
+ function Duration :__add (other )
226
+ if DEBUG then self :_debugOps (other ) end
227
+ -- normalize() handles adjustments to year and year_tick
228
+ return Duration { year = (self .year + other .year ), year_tick = (self .year_tick + other .year_tick ) }
229
+ end
230
+
231
+ function Duration :__sub (other )
232
+ if DEBUG then self :_debugOps (other ) end
233
+ -- normalize() handles adjustments to year and year_tick
234
+ return Duration { year = (self .year - other .year ) , year_tick = (self .year_tick - other .year_tick ) }
235
+ end
236
+
136
237
return _ENV
0 commit comments