Class: MarsDateTime
Constant Summary collapse
- VERSION =
"1.1.7"- MSEC_PER_SOL =
Really + 0.09
88775244- SOLS_PER_MYEAR =
668.5921- MSEC_PER_DAY =
86400000- FAKE_MSEC_PER_MYEAR =
(668*MSEC_PER_SOL)
- TimeStretch =
MSEC_PER_SOL/MSEC_PER_DAY.to_f
- Months =
%w[ UNDEFINED M-January Gemini M-February Cancer M-March Leo M-April Virgo M-May Libra M-June Scorpio M-July Sagittarius M-August Capricorn M-September Aquarius M-October Pisces M-November Aries M-December Taurus ]
- Week =
no month 0
%w[ Sunday Monday Tuesday Wednesday Thursday Friday Saturday ]
- EpochMCE =
DateTime.new(1,1,21)
- EpochCE =
DateTime.new(1,1,1)
- JulianDay1 =
Jan 1, 1 AD
1721445
Instance Attribute Summary collapse
-
#day_of_week ⇒ Object
readonly
Returns the value of attribute day_of_week.
-
#dow ⇒ Object
readonly
Returns the value of attribute dow.
-
#epoch_sol ⇒ Object
readonly
Returns the value of attribute epoch_sol.
-
#mems ⇒ Object
readonly
Returns the value of attribute mems.
-
#mhrs ⇒ Object
(also: #hr)
readonly
Returns the value of attribute mhrs.
-
#mmin ⇒ Object
(also: #min)
readonly
Returns the value of attribute mmin.
-
#month ⇒ Object
readonly
Returns the value of attribute month.
-
#msec ⇒ Object
(also: #sec)
readonly
Returns the value of attribute msec.
-
#shr ⇒ Object
readonly
stretched time.
-
#smin ⇒ Object
readonly
stretched time.
-
#sol ⇒ Object
readonly
Returns the value of attribute sol.
-
#ssec ⇒ Object
readonly
stretched time.
-
#year ⇒ Object
(also: #myear)
readonly
Returns the value of attribute year.
-
#year_sol ⇒ Object
readonly
Returns the value of attribute year_sol.
Class Method Summary collapse
-
.leap?(myear) ⇒ Boolean
class method for convenience.
-
.long?(myear) ⇒ Boolean
long year.
- .now ⇒ Object
-
.short?(myear) ⇒ Boolean
short year.
- .sols_in_month(m, year) ⇒ Object
- .today ⇒ Object
Instance Method Summary collapse
-
#+(sols) ⇒ Object
FIXME? sols or secs?.
-
#-(other) ⇒ Object
FIXME? sols or secs?.
- #<=>(other) ⇒ Object
- #check_ymshms(my, mm, msol, mhr = 0, mmin = 0, msec = 0) ⇒ Object
- #compute_stretched ⇒ Object
- #earth_date ⇒ Object
- #init_date(date) ⇒ Object
- #init_datetime(dt) ⇒ Object
- #init_mems(mems) ⇒ Object
- #init_yms(my, mm, msol, mhr = 0, mmin = 0, msec = 0) ⇒ Object
-
#initialize(*params) ⇒ MarsDateTime
constructor
A new instance of MarsDateTime.
- #inspect ⇒ Object
- #leap? ⇒ Boolean
- #leaps(myr) ⇒ Object
- #long? ⇒ Boolean
- #month_name ⇒ Object
- #short? ⇒ Boolean
- #strftime(fmt) ⇒ Object
- #to_s ⇒ Object
- #to_yaml_properties ⇒ Object
- #ymshms ⇒ Object
Constructor Details
#initialize(*params) ⇒ MarsDateTime
Returns a new instance of MarsDateTime.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/marsdate.rb', line 115 def initialize(*params) n = params.size case n when 3..6 init_yms(*params) when 0 init_datetime(DateTime.now) when 1 case params.first when Integer, Float init_mems(params.first) when Date init_date(params.first) when DateTime init_datetime(params.first) else raise "Expected number or DateTime" end else raise "Bad params: #{params.inspect}" end compute_stretched end |
Instance Attribute Details
#day_of_week ⇒ Object (readonly)
Returns the value of attribute day_of_week.
36 37 38 |
# File 'lib/marsdate.rb', line 36 def day_of_week @day_of_week end |
#dow ⇒ Object (readonly)
Returns the value of attribute dow.
36 37 38 |
# File 'lib/marsdate.rb', line 36 def dow @dow end |
#epoch_sol ⇒ Object (readonly)
Returns the value of attribute epoch_sol.
32 33 34 |
# File 'lib/marsdate.rb', line 32 def epoch_sol @epoch_sol end |
#mems ⇒ Object (readonly)
Returns the value of attribute mems.
34 35 36 |
# File 'lib/marsdate.rb', line 34 def mems @mems end |
#mhrs ⇒ Object (readonly) Also known as: hr
Returns the value of attribute mhrs.
37 38 39 |
# File 'lib/marsdate.rb', line 37 def mhrs @mhrs end |
#mmin ⇒ Object (readonly) Also known as: min
Returns the value of attribute mmin.
37 38 39 |
# File 'lib/marsdate.rb', line 37 def mmin @mmin end |
#month ⇒ Object (readonly)
Returns the value of attribute month.
32 33 34 |
# File 'lib/marsdate.rb', line 32 def month @month end |
#msec ⇒ Object (readonly) Also known as: sec
Returns the value of attribute msec.
37 38 39 |
# File 'lib/marsdate.rb', line 37 def msec @msec end |
#shr ⇒ Object (readonly)
stretched time
33 34 35 |
# File 'lib/marsdate.rb', line 33 def shr @shr end |
#smin ⇒ Object (readonly)
stretched time
33 34 35 |
# File 'lib/marsdate.rb', line 33 def smin @smin end |
#sol ⇒ Object (readonly)
Returns the value of attribute sol.
32 33 34 |
# File 'lib/marsdate.rb', line 32 def sol @sol end |
#ssec ⇒ Object (readonly)
stretched time
33 34 35 |
# File 'lib/marsdate.rb', line 33 def ssec @ssec end |
#year ⇒ Object (readonly) Also known as: myear
Returns the value of attribute year.
32 33 34 |
# File 'lib/marsdate.rb', line 32 def year @year end |
#year_sol ⇒ Object (readonly)
Returns the value of attribute year_sol.
32 33 34 |
# File 'lib/marsdate.rb', line 32 def year_sol @year_sol end |
Class Method Details
.leap?(myear) ⇒ Boolean
class method for convenience
44 45 46 47 48 49 |
# File 'lib/marsdate.rb', line 44 def self.leap?(myear) # class method for convenience return (myear % 2 == 1) if (myear % 10 != 0) return true if (myear % 1000 == 0) return false if (myear % 100 == 0) return true end |
.long?(myear) ⇒ Boolean
long year
55 56 57 |
# File 'lib/marsdate.rb', line 55 def self.long?(myear) # long year leap?(myear) end |
.now ⇒ Object
65 66 67 68 |
# File 'lib/marsdate.rb', line 65 def self.now d = DateTime.now MarsDateTime.new(d) end |
.short?(myear) ⇒ Boolean
short year
51 52 53 |
# File 'lib/marsdate.rb', line 51 def self.short?(myear) # short year !leap?(myear) end |
.sols_in_month(m, year) ⇒ Object
59 60 61 62 63 |
# File 'lib/marsdate.rb', line 59 def self.sols_in_month(m, year) return 28 if m < 24 return 25 if leap?(year) return 24 end |
.today ⇒ Object
70 71 72 73 |
# File 'lib/marsdate.rb', line 70 def self.today d = Date.today MarsDateTime.new(d) end |
Instance Method Details
#+(sols) ⇒ Object
FIXME? sols or secs?
241 242 243 244 |
# File 'lib/marsdate.rb', line 241 def +(sols) # FIXME? sols or secs? millisec = sols * MSEC_PER_SOL MarsDateTime.new(@mems + millisec) end |
#-(other) ⇒ Object
FIXME? sols or secs?
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/marsdate.rb', line 225 def -(other) # FIXME? sols or secs? case other when MarsDateTime diff = @mems - other.mems diff.to_f / MSEC_PER_SOL when DateTime other = MarsDateTime.new(other) diff = @mems - other.mems diff.to_f / MSEC_PER_SOL when Integer, Float self + (-other) else raise "Unexpected data type" end end |
#<=>(other) ⇒ Object
246 247 248 249 250 251 252 253 254 255 |
# File 'lib/marsdate.rb', line 246 def <=>(other) case other when MarsDateTime @mems <=> other.mems when DateTime @mems <=> MarsDateTime.new(other).mems else raise "Invalid comparison" end end |
#check_ymshms(my, mm, msol, mhr = 0, mmin = 0, msec = 0) ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/marsdate.rb', line 139 def check_ymshms(my, mm, msol, mhr=0, mmin=0, msec=0) text = "" text << "year #{my} is not an integer\n" unless my.is_a? Integer text << "month #{mm} is out of range" unless (1..24).include? mm text << "sol #{msol} is out of range" unless (1..28).include? msol text << "hour #{mhr} is out of range" unless (0..24).include? mhr text << "minute #{mmin} is out of range" unless (0..59).include? mmin text << "second #{msec} is out of range" unless (0..59).include? msec if !MarsDateTime.leap?(my) && mm == 24 && msol > 24 text << "sol #{msol} is invalid in a non-leap year" end raise text unless text.empty? end |
#compute_stretched ⇒ Object
167 168 169 170 171 172 173 174 |
# File 'lib/marsdate.rb', line 167 def compute_stretched # Handle stretched time... sec = @mhrs*3600 + @mmin*60 + @msec sec /= TimeStretch @shr, sec = sec.divmod(3600) @smin, sec = sec.divmod(60) @ssec = sec.round end |
#earth_date ⇒ Object
257 258 259 260 261 262 263 264 |
# File 'lib/marsdate.rb', line 257 def earth_date secs = @mems/1000 days,secs = secs.divmod(86400) hrs, secs = secs.divmod(3600) min, secs = secs.divmod(60) jday = days + JulianDay1 DateTime.jd(jday, hrs, min, secs) end |
#init_date(date) ⇒ Object
208 209 210 211 212 213 |
# File 'lib/marsdate.rb', line 208 def init_date(date) dt = date.to_datetime days = dt.jd - JulianDay1 secs = days*86400 + dt.hour*3600 + dt.min*60 + dt.sec init_mems(secs*1000) end |
#init_datetime(dt) ⇒ Object
215 216 217 218 219 |
# File 'lib/marsdate.rb', line 215 def init_datetime(dt) days = dt.jd - JulianDay1 secs = days*86400 + dt.hour*3600 + dt.min*60 + dt.sec init_mems(secs*1000) end |
#init_mems(mems) ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/marsdate.rb', line 176 def init_mems(mems) # Note: The sol length is off by 0.09 msec -- to properly fix this # will require measuring in microseconds so as to avoid floating-point math. # The "round" calls below were experimental and were "mostly" successful. full_years = 0 loop do millisec = FAKE_MSEC_PER_MYEAR millisec += MSEC_PER_SOL if MarsDateTime.leap?(full_years+1) break if mems < millisec mems -= millisec # puts "Subtracting #{millisec} -- one full year => #{mems}" full_years += 1 end mspm = MSEC_PER_SOL*28 full_months,mems = mems.divmod(mspm) full_days, mems = mems.divmod(MSEC_PER_SOL) full_hrs, mems = mems.divmod(3_600_000) full_min, mems = mems.divmod(60_000) sec = mems/1000.0 my = full_years + 1 # 1-based mm = full_months + 1 ms = full_days + 1 mhr = full_hrs # 0-based mmin = full_min msec = sec.to_i frac = sec - msec # fraction of a sec init_yms(my, mm, ms, mhr, mmin, msec) end |
#init_yms(my, mm, msol, mhr = 0, mmin = 0, msec = 0) ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/marsdate.rb', line 153 def init_yms(my, mm, msol, mhr=0, mmin=0, msec=0) check_ymshms(my, mm, msol, mhr, mmin, msec) zsol = msol - 1 # z means zero-based zmy = my - 1 # my means Martian year zesol = zmy*668 + leaps(my-1) + (mm-1)*28 + zsol # @mems is "Martian (time since) epoch in milliseconds" @mems = zesol*MSEC_PER_SOL + (mhr*3600 + mmin*60 + msec)*1000 @year, @month, @sol, @mhrs, @mmin, @msec = my, mm, msol, mhr, mmin, msec @epoch_sol = zesol + 1 @dow = (@epoch_sol-1) % 7 @day_of_week = Week[@dow] @year_sol = (mm-1)*28 + msol end |
#inspect ⇒ Object
85 86 87 88 89 90 |
# File 'lib/marsdate.rb', line 85 def inspect time = ('%02d' % @mhrs) + ":" + ('%02d' % @mmin) + ":" + ('%02d' % @msec) "#@year/#{'%02d' % @month}/#{'%02d' % @sol} " + "(#@year_sol, #@epoch_sol) #@day_of_week " + time end |
#leap? ⇒ Boolean
97 98 99 |
# File 'lib/marsdate.rb', line 97 def leap? MarsDateTime.leap?(@year) # DRY end |
#leaps(myr) ⇒ Object
75 76 77 78 79 |
# File 'lib/marsdate.rb', line 75 def leaps(myr) n = 0 1.upto(myr) {|i| n+=1 if MarsDateTime.leap?(i) } n end |
#long? ⇒ Boolean
105 106 107 |
# File 'lib/marsdate.rb', line 105 def long? leap? end |
#month_name ⇒ Object
109 110 111 |
# File 'lib/marsdate.rb', line 109 def month_name Months[@month] end |
#short? ⇒ Boolean
101 102 103 |
# File 'lib/marsdate.rb', line 101 def short? ! leap? end |
#strftime(fmt) ⇒ Object
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/marsdate.rb', line 266 def strftime(fmt) str = fmt.dup pieces = str.scan(/(%.|[^%]+)/).flatten final = "" zmonth = '%02d' % @month zsol = '%02d' % @sol zhh = '%02d' % @mhrs # stretched zmm = '%02d' % @mmin zss = '%02d' % @msec zhc = '%02d' % @shr # canonical zmc = '%02d' % @smin zsc = '%02d' % @ssec pieces.each do |piece| case piece when "%a"; final << @day_of_week[0..2] when "%A"; final << @day_of_week when "%b"; final << (@month.odd? ? month_name[2..4] : month_name[0..2]) when "%B"; final << month_name when "%d"; final << zsol when "%e"; final << ('%2d' % @sol) when "%F"; final << "#@year-#{zmonth}-#{zsol}" when "%H"; final << zhh when "%j"; final << @year_sol.to_s when "%m"; final << zmonth # @month.to_s when "%M"; final << zmm when "%s"; final << @msec.to_s # was: (@mems*1000).to_i.to_s when "%S"; final << zss when "%u"; final << (@dow + 1).to_s when "%U"; final << (@year_sol/7 + 1).to_s when "%w"; final << @dow.to_s when "%x"; final << "#@year/#{zmonth}/#{zsol}" when "%X"; final << "#{zhh}:#{zmm}:#{zss}" when "%Y"; final << @year.to_s when "%n"; final << "\n" when "%t"; final << "\t" when "%%"; final << "%" when "%P"; final << ("%02d" % @shr) when "%Q"; final << ("%02d" % @smin) when "%R"; final << ("%02d" % @ssec) else final << piece end end final end |
#to_s ⇒ Object
92 93 94 95 |
# File 'lib/marsdate.rb', line 92 def to_s time = self.strftime('%H:%M:%S [%P:%Q:%R]') "#@day_of_week, #{Months[@month]} #@sol, #@year at #{time}" end |
#to_yaml_properties ⇒ Object
81 82 83 |
# File 'lib/marsdate.rb', line 81 def to_yaml_properties %w[@myear @month @sol @epoch_sol @year_sol @dow @day_of_week @msme @mhrs @mmin @msec] end |
#ymshms ⇒ Object
221 222 223 |
# File 'lib/marsdate.rb', line 221 def ymshms [@year, @month, @sol, @mhrs, @mmin, @msec] end |