Class: Vanadiel::Time

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/vanadiel/time.rb

Overview

Vanadiel::Time is an abstraction of Vana'diel dates and times from Final Fantasy XI. Time is stored internally as the number of microseconds since C.E. 0001-01-01 00:00:00.

Vana'diel time spec:

One year   = 12 months = 360 days
One month  = 30 days
One day    = 24 hours
One hour   = 60 minutes
One minute = 60 seconds
One second = 0.04 seconds of the earth's (1/25th of a second)

Vana'diel second         = 0.04 earth seconds (1/25th of a second)
Vana'diel minute         = 2.4 earth seconds
Vana'diel hour           = 2 minutes 24 earth seconds
Vana'diel day            = 57 minutes 36 earth seconds
Vana'diel week           = 7 hours 40 minutes 48 earth seconds
Vana'diel calendar month = 1 day 4 hours 48 earth minutes
Vana'diel lunar month    = 3 days 14 hours 24 earth minutes
Vana'diel year           = 14 days 9 hours 36 earth minutes

Each full lunar cycle lasts for 84 Vana'diel days.
Vana'diel has 12 distinct moon phases.
Japanese client expresses moon phases by 12 kinds of texts. (percentage is not displayed in Japanese client)
Non-Japanese client expresses moon phases by 7 kinds of texts and percentage.

C.E. = Crystal Era

A.D. -91270800 => 1967/02/10 00:00:00 +0900
C.E. 0         => 0001/01/01 00:00:00

A.D. 2002/01/01(Tue) 00:00:00 JST
C.E. 0886/01/01(Fir) 00:00:00

A.D. 2047/10/22(Tue) 01:00:00 JST
C.E. 2047/10/22(Wat) 01:00:00

A.D. 2047/10/21(Mon) 15:37:30 UTC
C.E. 2047/10/21(Win) 15:37:30

Constant Summary collapse

VERSION =

vanadiel-time version

"0.2.1"
ONE_SECOND =
1000000
ONE_MINUTE =
60  * ONE_SECOND
ONE_HOUR =
60  * ONE_MINUTE
ONE_DAY =
24  * ONE_HOUR
ONE_WEEK =
8   * ONE_DAY
ONE_MONTH =
30  * ONE_DAY
ONE_YEAR =
360 * ONE_DAY
VANA_TIME_SCALE =

Vana'diel time goes 25 times faster than the Earth

25
VANA_BASE_YEAR =
886
VANA_BASE_TIME =
(VANA_BASE_YEAR * ONE_YEAR) / VANA_TIME_SCALE
EARTH_BASE_TIME =

2002/01/01 00:00:00.000 JST

1009810800 * ONE_SECOND
DIFF_TIME =
VANA_BASE_TIME - EARTH_BASE_TIME
MOON_CYCLE_DAYS =

Vana'diel moon cycle lasts 84 days

84

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#newTime #new(year, mon = 1, day = 1, hour = 0, min = 0, sec = 0, usec = 0) ⇒ Time

It is initialized to the current time if no argument. If one or more arguments specified, the time is initialized to the specified time.

Overloads:

  • #newTime

    It is initialized to the current time if no argument.

  • #new(year, mon = 1, day = 1, hour = 0, min = 0, sec = 0, usec = 0) ⇒ Time

    If one or more arguments specified, the time is initialized to the specified time.

    Parameters:

    • year (Integer)

      the year part (1..n)

    • mon (Integer) (defaults to: 1)

      the month part (1..12)

    • day (Integer) (defaults to: 1)

      the day of month part (1..30)

    • hour (Integer) (defaults to: 0)

      the hour part (0..23)

    • min (Integer) (defaults to: 0)

      the minute part (0..59)

    • sec (Integer) (defaults to: 0)

      the second part (0..59)

    • usec (Integer) (defaults to: 0)

      the microsecond part (0..999999)



128
129
130
# File 'lib/vanadiel/time.rb', line 128

def initialize(*args)
  self.time = args.empty? ? self.class.earth_to_vana(::Time.now.to_f * ONE_SECOND) : self.class.ymdhms_to_usec(*args)
end

Instance Attribute Details

#hourFixnum (readonly)

Returns the hour of the day (0..23) for time.

Returns:

  • (Fixnum)

    the hour of the day (0..23) for time



84
85
86
# File 'lib/vanadiel/time.rb', line 84

def hour
  @hour
end

#mdayFixnum (readonly) Also known as: day

Returns the day of the month (1..30) for time.

Returns:

  • (Fixnum)

    the day of the month (1..30) for time



80
81
82
# File 'lib/vanadiel/time.rb', line 80

def mday
  @mday
end

#minFixnum (readonly)

Returns the minute of the hour (0..59) for time.

Returns:

  • (Fixnum)

    the minute of the hour (0..59) for time



87
88
89
# File 'lib/vanadiel/time.rb', line 87

def min
  @min
end

#monthFixnum (readonly) Also known as: mon

Returns the month of the year (1..12) for time.

Returns:

  • (Fixnum)

    the month of the year (1..12) for time



74
75
76
# File 'lib/vanadiel/time.rb', line 74

def month
  @month
end

#moon_ageFixnum (readonly) Also known as: moon_age12

Returns an integer representing the moon age (0..11), for Japanese service.

Returns:

  • (Fixnum)

    an integer representing the moon age (0..11), for Japanese service



102
103
104
# File 'lib/vanadiel/time.rb', line 102

def moon_age
  @moon_age
end

#moon_age7Fixnum (readonly)

Returns an integer representing the moon age (0..7), for Non-Japanese service.

Returns:

  • (Fixnum)

    an integer representing the moon age (0..7), for Non-Japanese service



106
107
108
# File 'lib/vanadiel/time.rb', line 106

def moon_age7
  @moon_age7
end

#moon_percentFixnum (readonly)

Returns an integer representing the moon phase percentage (0..100), for Non-Japanese service.

Returns:

  • (Fixnum)

    an integer representing the moon phase percentage (0..100), for Non-Japanese service



109
110
111
# File 'lib/vanadiel/time.rb', line 109

def moon_percent
  @moon_percent
end

#secFixnum (readonly)

Returns the second of the minute (0..59) for time.

Returns:

  • (Fixnum)

    the second of the minute (0..59) for time



90
91
92
# File 'lib/vanadiel/time.rb', line 90

def sec
  @sec
end

#timeBignum

Returns the value of the time as microseconds since C.E. 0001-01-01 00:00:00.

Returns:

  • (Bignum)

    the value of the time as microseconds since C.E. 0001-01-01 00:00:00



68
69
70
# File 'lib/vanadiel/time.rb', line 68

def time
  @time
end

#time_of_moonFixnum (readonly)

Returns the number of microseconds of the moon.

Returns:

  • (Fixnum)

    the number of microseconds of the moon



112
113
114
# File 'lib/vanadiel/time.rb', line 112

def time_of_moon
  @time_of_moon
end

#usecFixnum (readonly)

Returns just the number of microseconds (0..999999) for time.

Returns:

  • (Fixnum)

    just the number of microseconds (0..999999) for time



93
94
95
# File 'lib/vanadiel/time.rb', line 93

def usec
  @usec
end

#wdayFixnum (readonly)

Returns an integer representing the day of the week, 0..7, with Firesday == 0.

Returns:

  • (Fixnum)

    an integer representing the day of the week, 0..7, with Firesday == 0



96
97
98
# File 'lib/vanadiel/time.rb', line 96

def wday
  @wday
end

#ydayFixnum (readonly)

Returns an integer representing the day of the year (1..360).

Returns:

  • (Fixnum)

    an integer representing the day of the year (1..360)



99
100
101
# File 'lib/vanadiel/time.rb', line 99

def yday
  @yday
end

#yearFixnum (readonly)

Returns the year for time.

Returns:

  • (Fixnum)

    the year for time



71
72
73
# File 'lib/vanadiel/time.rb', line 71

def year
  @year
end

Class Method Details

.at(time) ⇒ Vanadiel::Time .at(seconds, usec = 0) ⇒ Vanadiel::Time

Creates a new time object with the value given by time.

Overloads:

  • .at(time) ⇒ Vanadiel::Time

    Returns the time object initialized to the specified time.

    Parameters:

    Returns:

    • (Vanadiel::Time)

      the time object initialized to the specified time.

  • .at(seconds, usec = 0) ⇒ Vanadiel::Time

    Returns the time object initialized to the specified time.

    Parameters:

    • sec (Integer, Float)

      seconds from C.E. 0001-01-01 00:00:00

    • usec (Integer) (defaults to: 0)

      the microseconds

    Returns:

    • (Vanadiel::Time)

      the time object initialized to the specified time.



156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/vanadiel/time.rb', line 156

def self.at(time, usec = 0)
  obj = self.new
  if time.is_a? ::Time
    obj.time = self.earth_to_vana(time.to_f * ONE_SECOND)
  elsif time.is_a?(Vanadiel::Time)
    obj.time = time.time
  elsif time.is_a?(Integer) || time.is_a?(Float)
    obj.time = ((time * ONE_SECOND) + usec).to_i
  else
    raise ArgumentError, 'invalid argument'
  end
  obj
end

.earth_to_vana(earth_time) ⇒ Integer

Converts microseconds as the Earth time to microseconds as Vana'diel time from the Epoch.

Parameters:

  • earth_time (Integer)

    microseconds as the Earth time

Returns:

  • (Integer)

    microseconds as Vana'diel time



182
183
184
# File 'lib/vanadiel/time.rb', line 182

def self.earth_to_vana(earth_time)
  (earth_time + DIFF_TIME) * VANA_TIME_SCALE - ONE_YEAR
end

.mktime(year, *rest_part) ⇒ Vanadiel::Time

Same as Vanadiel::Time.new, but the year is required.

Returns:

  • (Vanadiel::Time)

    the time object initialized to the specified time.



142
143
144
145
# File 'lib/vanadiel/time.rb', line 142

def self.mktime(year, *rest_part)
  args = [year, *rest_part]
  self.new(*args)
end

.nowVanadiel::Time

Synonym for Vanadiel::Time.new. Returns a new time object initialized to the current time.

Returns:

  • (Vanadiel::Time)

    the time object initialized to the current time.



135
136
137
# File 'lib/vanadiel/time.rb', line 135

def self.now
  self.new
end

.vana_to_earth(vana_time) ⇒ Integer

Converts microseconds as Vana'diel time to microseconds as the Earth time from the Epoch.

Parameters:

  • vana_time (Integer)

    microseconds as Vana'diel time

Returns:

  • (Integer)

    microseconds as the Earth time



174
175
176
# File 'lib/vanadiel/time.rb', line 174

def self.vana_to_earth(vana_time)
   (((vana_time + ONE_YEAR) / VANA_TIME_SCALE) - DIFF_TIME)
end

.ymdhms_to_usec(year, mon = 1, day = 1, hour = 0, min = 0, sec = 0, usec = 0) ⇒ Integer

Converts to the value of time as an integer number of microseconds since C.E. 0001-01-01 00:00:00.

Parameters:

  • year (Integer)

    the year part (1..n)

  • mon (Integer) (defaults to: 1)

    the month part (1..12)

  • day (Integer) (defaults to: 1)

    the day of month part (1..30)

  • hour (Integer) (defaults to: 0)

    the hour part (0..23)

  • min (Integer) (defaults to: 0)

    the minute part (0..59)

  • sec (Integer) (defaults to: 0)

    the second part (0..59)

  • usec (Integer) (defaults to: 0)

    the microsecond part (0..999999)

Returns:

  • (Integer)

    microseconds as Vana'diel time

Raises:

  • (ArgumentError)


459
460
461
462
463
464
465
466
467
468
# File 'lib/vanadiel/time.rb', line 459

def self.ymdhms_to_usec(year, mon = 1, day = 1, hour = 0, min = 0, sec = 0, usec = 0)
  raise ArgumentError, 'year out of range' if year < 0
  raise ArgumentError, 'mon out of range'  if mon  < 1 || mon > 12
  raise ArgumentError, 'day out of range'  if day  < 1 || day > 30
  raise ArgumentError, 'hour out of range' if hour < 0 || hour > 23
  raise ArgumentError, 'min out of range'  if min  < 0 || min > 59
  raise ArgumentError, 'sec out of range'  if sec  < 0 || sec > 59
  raise ArgumentError, 'usec out of range' if usec < 0 || usec > 999999
  ((year - 1) * ONE_YEAR) + ((mon - 1) * ONE_MONTH) + ((day - 1) * ONE_DAY) + (hour * ONE_HOUR) + (min * ONE_MINUTE) + (sec * ONE_SECOND) + usec
end

Instance Method Details

#+(sec) ⇒ Vanadiel::Time

Adds some number of seconds (possibly fractional) to time and returns that value as a new time.

Parameters:

  • sec (Integer, Float)

    seconds

Returns:



355
356
357
# File 'lib/vanadiel/time.rb', line 355

def +(sec)
  self.class.at((@time + (sec * ONE_SECOND)) / ONE_SECOND)
end

#-(time) ⇒ Float #-(seconds) ⇒ Vanadiel::Time

Returns a new time that represents the difference between two times, or subtracts the given number of seconds in numeric from time.

Overloads:

  • #-(time) ⇒ Float

    Returns a new time that represents the difference between two times.

    Parameters:

    Returns:

    • (Float)

      seconds that represents the difference

  • #-(seconds) ⇒ Vanadiel::Time

    Subtracts the given number of seconds in numeric from time.

    Parameters:

    • sec (Integer, Float)

      seconds

    Returns:



370
371
372
373
374
375
376
377
378
379
380
# File 'lib/vanadiel/time.rb', line 370

def -(time)
  if time.is_a? ::Time
    (@time.to_f - self.class.earth_to_vana(time.to_f * ONE_SECOND)) / ONE_SECOND
  elsif time.is_a?(Vanadiel::Time)
    (@time.to_f - time.time) / ONE_SECOND
  elsif time.is_a?(Integer) || time.is_a?(Float)
    self.class.at((@time / ONE_SECOND) - time)
  else
    raise ArgumentError, 'invalid argument'
  end
end

#<=>(other_time) ⇒ -1, ...

Compares time with other time.

Parameters:

Returns:

  • (-1)

    if the time is earlier than the other time.

  • (0)

    if the time is same as the other time.

  • (1)

    if the time is later than the other time.

  • (nil)

    if it cannot compare.



389
390
391
# File 'lib/vanadiel/time.rb', line 389

def <=>(other_time)
  @time <=> other_time.time
end

#darksday?Boolean

Returns true if time represents Darksday.

Returns:

  • (Boolean)

    true if Darksday



224
# File 'lib/vanadiel/time.rb', line 224

def darksday?;      @wday == Vanadiel::Day::DARKSDAY;      end

#earthsday?Boolean

Returns true if time represents Earthsday.

Returns:

  • (Boolean)

    true if Earthsday



194
# File 'lib/vanadiel/time.rb', line 194

def earthsday?;     @wday == Vanadiel::Day::EARTHSDAY;     end

#eql?(other) ⇒ Boolean

Returns true if time and other time are both Vanadiel::Time objects with the same time.

Returns:

  • (Boolean)

    true if same



430
# File 'lib/vanadiel/time.rb', line 430

def eql?(other); self.hash == other.hash; end

#firesday?Boolean

Returns true if time represents Firesday.

Returns:

  • (Boolean)

    true if Firesday



189
# File 'lib/vanadiel/time.rb', line 189

def firesday?;      @wday == Vanadiel::Day::FIRESDAY;      end

#hashFixnum

Returns a hash code for this time object.

Returns:

  • (Fixnum)

    the hash code



425
# File 'lib/vanadiel/time.rb', line 425

def hash; @time.hash ^ self.class.hash; end

#iceday?Boolean

Returns true if time represents Iceday.

Returns:

  • (Boolean)

    true if Iceday



209
# File 'lib/vanadiel/time.rb', line 209

def iceday?;        @wday == Vanadiel::Day::ICEDAY;        end

#lightningday?Boolean

Returns true if time represents Lightningday.

Returns:

  • (Boolean)

    true if Lightningday



214
# File 'lib/vanadiel/time.rb', line 214

def lightningday?;  @wday == Vanadiel::Day::LIGHTNINGDAY;  end

#lightsday?Boolean

Returns true if time represents Lightsday.

Returns:

  • (Boolean)

    true if Lightsday



219
# File 'lib/vanadiel/time.rb', line 219

def lightsday?;     @wday == Vanadiel::Day::LIGHTSDAY;     end

#marshal_dumpObject



441
442
443
# File 'lib/vanadiel/time.rb', line 441

def marshal_dump
  @time
end

#marshal_load(obj) ⇒ Object



445
446
447
# File 'lib/vanadiel/time.rb', line 445

def marshal_load(obj)
  self.time = obj
end

#strftime(format) ⇒ String

Format Vana'diel time according to the directives in the format string. The directives begins with a percent (%) character. Any text not listed as a directive will be passed through to the output string.

The directive consists of a percent (%) character, zero or more flags, optional minimum field width and a conversion specifier as follows.

%<flags><width><conversion>

Flags:

-  don't pad a numerical output.
_  use spaces for padding.
0  use zeros for padding.
^  upcase the result string.
#  change case.

The minimum field width specifies the minimum width.

Format directives:

Date (Year, Month, Day):
  %Y - Year with century (can be negative)
          -0001, 0000, 1995, 2009, 14292, etc.
  %C - year / 100 (round down.  20 in 2009)
  %y - year % 100 (00..99)

  %m - Month of the year, zero-padded (01..12)
          %_m  blank-padded ( 1..12)
          %-m  no-padded (1..12)

  %d - Day of the month, zero-padded (01..30)
          %-d  no-padded (1..30)
  %e - Day of the month, blank-padded ( 1..30)

  %j - Day of the year (001..360)

Time (Hour, Minute, Second, Subsecond):
  %H - Hour of the day, 24-hour clock, zero-padded (00..23)
  %k - Hour of the day, 24-hour clock, blank-padded ( 0..23)

  %M - Minute of the hour (00..59)

  %S - Second of the minute (00..59)

  %L - Millisecond of the second (000..999)
  %N - Fractional seconds digits, default is 6 digits (microsecond)
          %3N  millisecond (3 digits)
          %6N  microsecond (6 digits)

Weekday:
  %A - The full weekday name (``Firesday'')
          %^A  uppercased (``FIRESDAY'')
  %w - Day of the week (Firesday is 0, 0..7)

Seconds since the Epoch:
  %s - Number of seconds since 0001-01-01 00:00:00

Literal string:
  %n - Newline character (\n)
  %t - Tab character (\t)
  %% - Literal ``%'' character

Combination:
  %F - The ISO 8601 date format (%Y-%m-%d)
  %X - Same as %T
  %R - 24-hour time (%H:%M)
  %T - 24-hour time (%H:%M:%S)

Parameters:

  • format (String)

    the format string

Returns:

  • (String)

    formatted string



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'lib/vanadiel/time.rb', line 297

def strftime(format)
  source = { 'Y' => @year,  'C' => @year / 100, 'y' => @year % 100,
             'm' => @month, 'd' => @mday, 'e' => @mday, 'j' => @yday,
             'H' => @hour,  'k' => @hour, 'M' => @min,  'S' => @sec, 'L' => @usec, 'N' => @usec,
             'A' => @wday,  'w' => @wday, 's' => @time,
             'n' => "\n",   't' => "\t",  '%' => '%' }
  default_padding = { 'e' => ' ', 'k' => ' ', 'A' => ' ', 'n' => ' ', 't' => ' ', '%' => ' ' }
  default_padding.default = '0'
  default_width = { 'y' => 2, 'm' => 2, 'd' => 2, 'e' => 2, 'H' => 2, 'k' => 2, 'M' => 2, 'S' => 2,
                    'j' => 3, 'L' => 3,
                    'N' => 6 }
  default_width.default = 0

  format.gsub(/%([-_0^#]+)?(\d+)?([FXRT])/) {
    case $3
    when 'F'      then '%Y-%m-%d'
    when 'T', 'X' then '%H:%M:%S'
    when 'R'      then '%H:%M'
    end
  }.gsub(/%([-_0^#]+)?(\d+)?([YCymdejHkMSLNAawsnt%])/) {|s|
    flags = $1; width = $2.to_i; conversion = $3; upcase = false
    padding = default_padding[conversion]
    width = default_width[conversion] if width.zero?
    v = source[conversion]

    flags.each_char {|c|
      case c
      when '-' then padding = nil
      when '_' then padding = ' '
      when '0' then padding = '0'
      when '^', '#' then upcase = true
      end
    } if flags

    case conversion
    when 'L', 'N'
      if (width <= 6)
        v = v / (100000 / (10 ** (width - 1)))
      else
        v = v * (10 ** (width - 6))
      end
    when 'A'
      v = Vanadiel::Day::DAYNAMES[v]
    end

    v = v.to_s
    if width > 0 && padding && v.length < width
      v = (padding * (width - v.length)) + v
    end

    upcase ? v.upcase : v
  }
end

#to_earth_time::Time

Returns the value of time as the Earth time object.

Returns:

  • (::Time)

    the Earth time object



418
419
420
# File 'lib/vanadiel/time.rb', line 418

def to_earth_time
  ::Time.at(self.class.vana_to_earth(@time) / ONE_SECOND)
end

#to_fInteger

Returns the value of time as an integer number of seconds since C.E. 0001-01-01 00:00:00.

Returns:

  • (Integer)

    seconds



403
404
405
# File 'lib/vanadiel/time.rb', line 403

def to_f
  @time.to_f / ONE_SECOND
end

#to_iFloat

Returns the value of time as a floating point number of seconds since C.E. 0001-01-01 00:00:00.

Returns:

  • (Float)

    seconds



396
397
398
# File 'lib/vanadiel/time.rb', line 396

def to_i
  @time / ONE_SECOND
end

#to_sString

Returns a string representing time. Equivalent to calling #strftime with a format string of "%Y-%m-%d %H:%M:%S".

Returns:

  • (String)

    the string representing time



411
412
413
# File 'lib/vanadiel/time.rb', line 411

def to_s
  self.strftime('%Y-%m-%d %H:%M:%S')
end

#watersday?Boolean

Returns true if time represents Watersday.

Returns:

  • (Boolean)

    true if Watersday



199
# File 'lib/vanadiel/time.rb', line 199

def watersday?;     @wday == Vanadiel::Day::WATERSDAY;     end

#windsday?Boolean

Returns true if time represents Windsday.

Returns:

  • (Boolean)

    true if Windsday



204
# File 'lib/vanadiel/time.rb', line 204

def windsday?;      @wday == Vanadiel::Day::WINDSDAY;      end