Class: Vanadiel::Time

Inherits:
Object
  • Object
show all
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.1.0"
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)



126
127
128
# File 'lib/vanadiel/time.rb', line 126

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



82
83
84
# File 'lib/vanadiel/time.rb', line 82

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



78
79
80
# File 'lib/vanadiel/time.rb', line 78

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



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

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



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

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



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

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



104
105
106
# File 'lib/vanadiel/time.rb', line 104

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



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

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



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

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



66
67
68
# File 'lib/vanadiel/time.rb', line 66

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



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

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



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

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



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

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)



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

def yday
  @yday
end

#yearFixnum (readonly)

Returns the year for time.

Returns:

  • (Fixnum)

    the year for time



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

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.



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

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



180
181
182
# File 'lib/vanadiel/time.rb', line 180

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.



140
141
142
143
# File 'lib/vanadiel/time.rb', line 140

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.



133
134
135
# File 'lib/vanadiel/time.rb', line 133

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



172
173
174
# File 'lib/vanadiel/time.rb', line 172

def self.vana_to_earth(vana_time)
   earth = (((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)


462
463
464
465
466
467
468
469
470
471
# File 'lib/vanadiel/time.rb', line 462

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:



353
354
355
# File 'lib/vanadiel/time.rb', line 353

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:



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

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.



387
388
389
# File 'lib/vanadiel/time.rb', line 387

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

#==(other) ⇒ Boolean

Returns true if time and other time are the same time.

Returns:

  • (Boolean)

    true if same



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

def ==(other);   @time == other.time;     end

#darksday?Boolean

Returns true if time represents Darksday.

Returns:

  • (Boolean)

    true if Darksday



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

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

#earthsday?Boolean

Returns true if time represents Earthsday.

Returns:

  • (Boolean)

    true if Earthsday



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

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



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

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

#firesday?Boolean

Returns true if time represents Firesday.

Returns:

  • (Boolean)

    true if Firesday



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

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

#hashFixnum

Returns a hash code for this time object.

Returns:

  • (Fixnum)

    the hash code



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

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

#iceday?Boolean

Returns true if time represents Iceday.

Returns:

  • (Boolean)

    true if Iceday



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

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

#lightningday?Boolean

Returns true if time represents Lightningday.

Returns:

  • (Boolean)

    true if Lightningday



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

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

#lightsday?Boolean

Returns true if time represents Lightsday.

Returns:

  • (Boolean)

    true if Lightsday



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

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

#marshal_dumpObject



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

def marshal_dump
  @time
end

#marshal_load(obj) ⇒ Object



448
449
450
# File 'lib/vanadiel/time.rb', line 448

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



295
296
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
# File 'lib/vanadiel/time.rb', line 295

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



416
417
418
# File 'lib/vanadiel/time.rb', line 416

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



401
402
403
# File 'lib/vanadiel/time.rb', line 401

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



394
395
396
# File 'lib/vanadiel/time.rb', line 394

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



409
410
411
# File 'lib/vanadiel/time.rb', line 409

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



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

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

#windsday?Boolean

Returns true if time represents Windsday.

Returns:

  • (Boolean)

    true if Windsday



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

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