vanadiel-time 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +3 -0
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +4 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +47 -0
- data/Rakefile +34 -0
- data/examples/clock.rb +12 -0
- data/lib/vanadiel/day.rb +29 -0
- data/lib/vanadiel/moon.rb +91 -0
- data/lib/vanadiel/time.rb +533 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/time_spec.rb +682 -0
- data/vanadiel-time.gemspec +26 -0
- metadata +149 -0
data/.document
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour --format documentation
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown --title "vanadiel-time Documentation" --protected
|
data/ChangeLog.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Yuki
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# vanadiel-time
|
2
|
+
|
3
|
+
* [Homepage](https://github.com/pasela/vanadiel-time-gem)
|
4
|
+
* [Issues](https://github.com/pasela/vanadiel-time-gem/issues)
|
5
|
+
* [Documentation](http://rubydoc.info/gems/vanadiel-time/frames)
|
6
|
+
* [Email](mailto:paselan at gmail.com )
|
7
|
+
|
8
|
+
## Description
|
9
|
+
|
10
|
+
A library for dealing with Vana'diel time from Final Fantasy XI.
|
11
|
+
Converting between realtime and Vana'diel time, and so on.
|
12
|
+
|
13
|
+
## Examples
|
14
|
+
|
15
|
+
require 'vanadiel/time'
|
16
|
+
|
17
|
+
p Vanadiel::Time.now #=> 1156-09-01 10:31:27
|
18
|
+
p Vanadiel::Time.new(1156, 2, 4, 10, 15, 30) #=> 1156-02-04 10:15:30
|
19
|
+
|
20
|
+
Another example:
|
21
|
+
|
22
|
+
require 'vanadiel/time'
|
23
|
+
|
24
|
+
et = Time.now
|
25
|
+
vt = Vanadiel::Time.at(et)
|
26
|
+
|
27
|
+
puts "Earth : %s" % et.strftime("%Y-%m-%d %H:%M:%S %A")
|
28
|
+
puts "Vana'diel: %s" % vt.strftime("%Y-%m-%d %H:%M:%S %A")
|
29
|
+
puts " %s %s (%d%%)" % [Vanadiel::Moon::MOONNAMES_JA[vt.moon_age],
|
30
|
+
Vanadiel::Moon::MOONNAMES[vt.moon_age],
|
31
|
+
vt.moon_percent]
|
32
|
+
|
33
|
+
output:
|
34
|
+
|
35
|
+
Earth : 2012-09-02 02:58:43 Sunday
|
36
|
+
Vana'diel: 1156-08-19 02:28:06 Iceday
|
37
|
+
二十日余月 Waning Crescent (38%)
|
38
|
+
|
39
|
+
## Install
|
40
|
+
|
41
|
+
$ gem install vanadiel-time
|
42
|
+
|
43
|
+
## Copyright
|
44
|
+
|
45
|
+
Copyright (c) 2012 Yuki
|
46
|
+
|
47
|
+
See {file:LICENSE.txt} for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler'
|
7
|
+
rescue LoadError => e
|
8
|
+
warn e.message
|
9
|
+
warn "Run `gem install bundler` to install Bundler."
|
10
|
+
exit -1
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
Bundler.setup(:development)
|
15
|
+
rescue Bundler::BundlerError => e
|
16
|
+
warn e.message
|
17
|
+
warn "Run `bundle install` to install missing gems."
|
18
|
+
exit e.status_code
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake'
|
22
|
+
|
23
|
+
require 'rubygems/tasks'
|
24
|
+
Gem::Tasks.new
|
25
|
+
|
26
|
+
require 'rspec/core/rake_task'
|
27
|
+
RSpec::Core::RakeTask.new
|
28
|
+
|
29
|
+
task :test => :spec
|
30
|
+
task :default => :spec
|
31
|
+
|
32
|
+
require 'yard'
|
33
|
+
YARD::Rake::YardocTask.new
|
34
|
+
task :doc => :yard
|
data/examples/clock.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'vanadiel/time'
|
4
|
+
|
5
|
+
et = Time.now
|
6
|
+
vt = Vanadiel::Time.at(et)
|
7
|
+
|
8
|
+
puts "Earth : %s" % et.strftime("%Y-%m-%d %H:%M:%S %A")
|
9
|
+
puts "Vana'diel: %s" % vt.strftime("%Y-%m-%d %H:%M:%S %A")
|
10
|
+
puts " %s %s (%d%%)" % [Vanadiel::Moon::MOONNAMES_JA[vt.moon_age],
|
11
|
+
Vanadiel::Moon::MOONNAMES[vt.moon_age],
|
12
|
+
vt.moon_percent]
|
data/lib/vanadiel/day.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Vanadiel
|
4
|
+
# Vanadiel::Day has some constants about Vana'diel days.
|
5
|
+
module Day
|
6
|
+
# 火曜日
|
7
|
+
FIRESDAY = 0
|
8
|
+
# 土曜日
|
9
|
+
EARTHSDAY = 1
|
10
|
+
# 水曜日
|
11
|
+
WATERSDAY = 2
|
12
|
+
# 風曜日
|
13
|
+
WINDSDAY = 3
|
14
|
+
# 氷曜日
|
15
|
+
ICEDAY = 4
|
16
|
+
# 雷曜日
|
17
|
+
LIGHTNINGDAY = 5
|
18
|
+
# 光曜日
|
19
|
+
LIGHTSDAY = 6
|
20
|
+
# 闇曜日
|
21
|
+
DARKSDAY = 7
|
22
|
+
|
23
|
+
# Day names
|
24
|
+
DAYNAMES = ['Firesday', 'Earthsday', 'Watersday', 'Windsday', 'Iceday', 'Lightningday', 'Lightsday', 'Darksday']
|
25
|
+
|
26
|
+
# Day names for Japanese
|
27
|
+
DAYNAMES_JA = ['火曜日', '土曜日', '水曜日', '風曜日', '氷曜日', '雷曜日', '光曜日', '闇曜日']
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Vanadiel
|
4
|
+
# Vanadiel::Moon has some constants about Vana'diel moon phases (12 steps version).
|
5
|
+
#
|
6
|
+
# moon phase (0..11, for Japanese service)
|
7
|
+
module Moon
|
8
|
+
# 新月
|
9
|
+
NEW_MOON = 0
|
10
|
+
# 三日月
|
11
|
+
WAXING_CRESCENT1 = 1
|
12
|
+
# 七日月
|
13
|
+
WAXING_CRESCENT2 = 2
|
14
|
+
# 上弦の月
|
15
|
+
FIRST_QUARTER = 3
|
16
|
+
# 十日夜
|
17
|
+
WAXING_GIBBOUS1 = 4
|
18
|
+
# 十三夜
|
19
|
+
WAXING_GIBBOUS2 = 5
|
20
|
+
# 満月
|
21
|
+
FULL_MOON = 6
|
22
|
+
# 十六夜
|
23
|
+
WANING_GIBBOUS1 = 7
|
24
|
+
# 居待月
|
25
|
+
WANING_GIBBOUS2 = 8
|
26
|
+
# 下弦の月
|
27
|
+
LAST_QUARTER = 9
|
28
|
+
# 二十日余月
|
29
|
+
WANING_CRESCENT1 = 10
|
30
|
+
# 二十六夜
|
31
|
+
WANING_CRESCENT2 = 11
|
32
|
+
|
33
|
+
# Moon phase names
|
34
|
+
MOONNAMES = [
|
35
|
+
'New Moon',
|
36
|
+
'Waxing Crescent',
|
37
|
+
'Waxing Crescent',
|
38
|
+
'First Quarter',
|
39
|
+
'Waxing Gibbous',
|
40
|
+
'Waxing Gibbous',
|
41
|
+
'Full Moon',
|
42
|
+
'Waning Gibbous',
|
43
|
+
'Waning Gibbous',
|
44
|
+
'Last Quarter',
|
45
|
+
'Waning Crescent',
|
46
|
+
'Waning Crescent',
|
47
|
+
]
|
48
|
+
|
49
|
+
# Moon phase names for Japanese
|
50
|
+
MOONNAMES_JA = [
|
51
|
+
'新月',
|
52
|
+
'三日月',
|
53
|
+
'七日月',
|
54
|
+
'上弦の月',
|
55
|
+
'十日夜',
|
56
|
+
'十三夜',
|
57
|
+
'満月',
|
58
|
+
'十六夜',
|
59
|
+
'居待月',
|
60
|
+
'下弦の月',
|
61
|
+
'二十日余月',
|
62
|
+
'二十六夜',
|
63
|
+
]
|
64
|
+
end
|
65
|
+
|
66
|
+
# Vanadiel::Moon7 has some constants about Vana'diel moon phases (8 steps version).
|
67
|
+
#
|
68
|
+
# moon phase (0..7, for Non-Japanese service)
|
69
|
+
module Moon7
|
70
|
+
NEW_MOON = 0
|
71
|
+
WAXING_CRESCENT = 1
|
72
|
+
FIRST_QUARTER = 2
|
73
|
+
WAXING_GIBBOUS = 3
|
74
|
+
FULL_MOON = 4
|
75
|
+
WANING_GIBBOUS = 5
|
76
|
+
LAST_QUARTER = 6
|
77
|
+
WANING_CRESCENT = 7
|
78
|
+
|
79
|
+
# Moon phase names
|
80
|
+
MOONNAMES = [
|
81
|
+
'New Moon',
|
82
|
+
'Waxing Crescent',
|
83
|
+
'First Quarter',
|
84
|
+
'Waxing Gibbous',
|
85
|
+
'Full Moon',
|
86
|
+
'Waning Gibbous',
|
87
|
+
'Last Quarter',
|
88
|
+
'Waning Crescent',
|
89
|
+
]
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,533 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'vanadiel/day'
|
4
|
+
require 'vanadiel/moon'
|
5
|
+
|
6
|
+
module Vanadiel
|
7
|
+
# Vanadiel::Time is an abstraction of Vana'diel dates and times from Final Fantasy XI.
|
8
|
+
# Time is stored internally as the number of microseconds since C.E. 0001-01-01 00:00:00.
|
9
|
+
#
|
10
|
+
# Vana'diel time spec:
|
11
|
+
#
|
12
|
+
# One year = 12 months = 360 days
|
13
|
+
# One month = 30 days
|
14
|
+
# One day = 24 hours
|
15
|
+
# One hour = 60 minutes
|
16
|
+
# One minute = 60 seconds
|
17
|
+
# One second = 0.04 seconds of the earth's (1/25th of a second)
|
18
|
+
#
|
19
|
+
# Vana'diel second = 0.04 earth seconds (1/25th of a second)
|
20
|
+
# Vana'diel minute = 2.4 earth seconds
|
21
|
+
# Vana'diel hour = 2 minutes 24 earth seconds
|
22
|
+
# Vana'diel day = 57 minutes 36 earth seconds
|
23
|
+
# Vana'diel week = 7 hours 40 minutes 48 earth seconds
|
24
|
+
# Vana'diel calendar month = 1 day 4 hours 48 earth minutes
|
25
|
+
# Vana'diel lunar month = 3 days 14 hours 24 earth minutes
|
26
|
+
# Vana'diel year = 14 days 9 hours 36 earth minutes
|
27
|
+
#
|
28
|
+
# Each full lunar cycle lasts for 84 Vana'diel days.
|
29
|
+
# Vana'diel has 12 distinct moon phases.
|
30
|
+
# Japanese client expresses moon phases by 12 kinds of texts. (percentage is not displayed in Japanese client)
|
31
|
+
# Non-Japanese client expresses moon phases by 7 kinds of texts and percentage.
|
32
|
+
#
|
33
|
+
# C.E. = Crystal Era
|
34
|
+
#
|
35
|
+
# A.D. -91270800 => 1967/02/10 00:00:00 +0900
|
36
|
+
# C.E. 0 => 0001/01/01 00:00:00
|
37
|
+
#
|
38
|
+
# A.D. 2002/01/01(Tue) 00:00:00 JST
|
39
|
+
# C.E. 0886/01/01(Fir) 00:00:00
|
40
|
+
#
|
41
|
+
# A.D. 2047/10/22(Tue) 01:00:00 JST
|
42
|
+
# C.E. 2047/10/22(Wat) 01:00:00
|
43
|
+
#
|
44
|
+
# A.D. 2047/10/21(Mon) 15:37:30 UTC
|
45
|
+
# C.E. 2047/10/21(Win) 15:37:30
|
46
|
+
class Time
|
47
|
+
# vanadiel-time version
|
48
|
+
VERSION = "0.1.0"
|
49
|
+
|
50
|
+
ONE_SECOND = 1000000
|
51
|
+
ONE_MINUTE = 60 * ONE_SECOND
|
52
|
+
ONE_HOUR = 60 * ONE_MINUTE
|
53
|
+
ONE_DAY = 24 * ONE_HOUR
|
54
|
+
ONE_WEEK = 8 * ONE_DAY
|
55
|
+
ONE_MONTH = 30 * ONE_DAY
|
56
|
+
ONE_YEAR = 360 * ONE_DAY
|
57
|
+
|
58
|
+
VANA_TIME_SCALE = 25 # Vana'diel time goes 25 times faster than the Earth
|
59
|
+
VANA_BASE_YEAR = 886
|
60
|
+
VANA_BASE_TIME = (VANA_BASE_YEAR * ONE_YEAR) / VANA_TIME_SCALE
|
61
|
+
EARTH_BASE_TIME = 1009810800 * ONE_SECOND # 2002/01/01 00:00:00.000 JST
|
62
|
+
DIFF_TIME = VANA_BASE_TIME - EARTH_BASE_TIME
|
63
|
+
MOON_CYCLE_DAYS = 84 # Vana'diel moon cycle lasts 84 days
|
64
|
+
|
65
|
+
# @return [Bignum] the value of the time as microseconds since C.E. 0001-01-01 00:00:00
|
66
|
+
attr_reader :time
|
67
|
+
|
68
|
+
# @return [Fixnum] the year for time
|
69
|
+
attr_reader :year
|
70
|
+
|
71
|
+
# @return [Fixnum] the month of the year (1..12) for time
|
72
|
+
attr_reader :month
|
73
|
+
|
74
|
+
# @return [Fixnum] the month of the year (1..12) for time
|
75
|
+
alias_method :mon, :month
|
76
|
+
|
77
|
+
# @return [Fixnum] the day of the month (1..30) for time
|
78
|
+
attr_reader :mday
|
79
|
+
alias_method :day, :mday
|
80
|
+
|
81
|
+
# @return [Fixnum] the hour of the day (0..23) for time
|
82
|
+
attr_reader :hour
|
83
|
+
|
84
|
+
# @return [Fixnum] the minute of the hour (0..59) for time
|
85
|
+
attr_reader :min
|
86
|
+
|
87
|
+
# @return [Fixnum] the second of the minute (0..59) for time
|
88
|
+
attr_reader :sec
|
89
|
+
|
90
|
+
# @return [Fixnum] just the number of microseconds (0..999999) for time
|
91
|
+
attr_reader :usec
|
92
|
+
|
93
|
+
# @return [Fixnum] an integer representing the day of the week, 0..7, with Firesday == 0
|
94
|
+
attr_reader :wday
|
95
|
+
|
96
|
+
# @return [Fixnum] an integer representing the day of the year (1..360)
|
97
|
+
attr_reader :yday
|
98
|
+
|
99
|
+
# @return [Fixnum] an integer representing the moon age (0..11), for Japanese service
|
100
|
+
attr_reader :moon_age
|
101
|
+
alias_method :moon_age12, :moon_age
|
102
|
+
|
103
|
+
# @return [Fixnum] an integer representing the moon age (0..7), for Non-Japanese service
|
104
|
+
attr_reader :moon_age7
|
105
|
+
|
106
|
+
# @return [Fixnum] an integer representing the moon phase percentage (0..100), for Non-Japanese service
|
107
|
+
attr_reader :moon_percent
|
108
|
+
|
109
|
+
# @return [Fixnum] the number of microseconds of the moon
|
110
|
+
attr_reader :time_of_moon
|
111
|
+
|
112
|
+
# It is initialized to the current time if no argument.
|
113
|
+
# If one or more arguments specified, the time is initialized to the specified time.
|
114
|
+
#
|
115
|
+
# @overload new()
|
116
|
+
# It is initialized to the current time if no argument.
|
117
|
+
# @overload new(year, mon = 1, day = 1, hour = 0, min = 0, sec = 0, usec = 0)
|
118
|
+
# If one or more arguments specified, the time is initialized to the specified time.
|
119
|
+
# @param [Integer] year the year part (1..n)
|
120
|
+
# @param [Integer] mon the month part (1..12)
|
121
|
+
# @param [Integer] day the day of month part (1..30)
|
122
|
+
# @param [Integer] hour the hour part (0..23)
|
123
|
+
# @param [Integer] min the minute part (0..59)
|
124
|
+
# @param [Integer] sec the second part (0..59)
|
125
|
+
# @param [Integer] usec the microsecond part (0..999999)
|
126
|
+
def initialize(*args)
|
127
|
+
self.time = args.empty? ? self.class.earth_to_vana(::Time.now.to_f * ONE_SECOND) : self.class.ymdhms_to_usec(*args)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Synonym for Vanadiel::Time.new. Returns a new time object initialized to the current time.
|
131
|
+
#
|
132
|
+
# @return [Vanadiel::Time] the time object initialized to the current time.
|
133
|
+
def self.now
|
134
|
+
self.new
|
135
|
+
end
|
136
|
+
|
137
|
+
# Same as Vanadiel::Time.new, but the year is required.
|
138
|
+
#
|
139
|
+
# @return [Vanadiel::Time] the time object initialized to the specified time.
|
140
|
+
def self.mktime(year, *rest_part)
|
141
|
+
args = [year, *rest_part]
|
142
|
+
self.new(*args)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Creates a new time object with the value given by time.
|
146
|
+
#
|
147
|
+
# @overload at(time)
|
148
|
+
# @param [::Time, Vanadiel::Time] time the time object
|
149
|
+
# @return [Vanadiel::Time] the time object initialized to the specified time.
|
150
|
+
# @overload at(seconds, usec = 0)
|
151
|
+
# @param [Integer, Float] sec seconds from C.E. 0001-01-01 00:00:00
|
152
|
+
# @param [Integer] usec the microseconds
|
153
|
+
# @return [Vanadiel::Time] the time object initialized to the specified time.
|
154
|
+
def self.at(time, usec = 0)
|
155
|
+
obj = self.new
|
156
|
+
if time.is_a? ::Time
|
157
|
+
obj.time = self.earth_to_vana(time.to_f * ONE_SECOND)
|
158
|
+
elsif time.is_a?(Vanadiel::Time)
|
159
|
+
obj.time = time.time
|
160
|
+
elsif time.is_a?(Integer) || time.is_a?(Float)
|
161
|
+
obj.time = ((time * ONE_SECOND) + usec).to_i
|
162
|
+
else
|
163
|
+
raise ArgumentError, 'invalid argument'
|
164
|
+
end
|
165
|
+
obj
|
166
|
+
end
|
167
|
+
|
168
|
+
# Converts microseconds as Vana'diel time to microseconds as the Earth time from the Epoch.
|
169
|
+
#
|
170
|
+
# @param [Integer] vana_time microseconds as Vana'diel time
|
171
|
+
# @return [Integer] microseconds as the Earth time
|
172
|
+
def self.vana_to_earth(vana_time)
|
173
|
+
earth = (((vana_time + ONE_YEAR) / VANA_TIME_SCALE) - DIFF_TIME)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Converts microseconds as the Earth time to microseconds as Vana'diel time from the Epoch.
|
177
|
+
#
|
178
|
+
# @param [Integer] earth_time microseconds as the Earth time
|
179
|
+
# @return [Integer] microseconds as Vana'diel time
|
180
|
+
def self.earth_to_vana(earth_time)
|
181
|
+
(earth_time + DIFF_TIME) * VANA_TIME_SCALE - ONE_YEAR
|
182
|
+
end
|
183
|
+
|
184
|
+
# Returns true if time represents Firesday.
|
185
|
+
#
|
186
|
+
# @return [Boolean] true if Firesday
|
187
|
+
def firesday?; @wday == Vanadiel::Day::FIRESDAY; end
|
188
|
+
|
189
|
+
# Returns true if time represents Earthsday.
|
190
|
+
#
|
191
|
+
# @return [Boolean] true if Earthsday
|
192
|
+
def earthsday?; @wday == Vanadiel::Day::EARTHSDAY; end
|
193
|
+
|
194
|
+
# Returns true if time represents Watersday.
|
195
|
+
#
|
196
|
+
# @return [Boolean] true if Watersday
|
197
|
+
def watersday?; @wday == Vanadiel::Day::WATERSDAY; end
|
198
|
+
|
199
|
+
# Returns true if time represents Windsday.
|
200
|
+
#
|
201
|
+
# @return [Boolean] true if Windsday
|
202
|
+
def windsday?; @wday == Vanadiel::Day::WINDSDAY; end
|
203
|
+
|
204
|
+
# Returns true if time represents Iceday.
|
205
|
+
#
|
206
|
+
# @return [Boolean] true if Iceday
|
207
|
+
def iceday?; @wday == Vanadiel::Day::ICEDAY; end
|
208
|
+
|
209
|
+
# Returns true if time represents Lightningday.
|
210
|
+
#
|
211
|
+
# @return [Boolean] true if Lightningday
|
212
|
+
def lightningday?; @wday == Vanadiel::Day::LIGHTNINGDAY; end
|
213
|
+
|
214
|
+
# Returns true if time represents Lightsday.
|
215
|
+
#
|
216
|
+
# @return [Boolean] true if Lightsday
|
217
|
+
def lightsday?; @wday == Vanadiel::Day::LIGHTSDAY; end
|
218
|
+
|
219
|
+
# Returns true if time represents Darksday.
|
220
|
+
#
|
221
|
+
# @return [Boolean] true if Darksday
|
222
|
+
def darksday?; @wday == Vanadiel::Day::DARKSDAY; end
|
223
|
+
|
224
|
+
# Format Vana'diel time according to the directives in the format string.
|
225
|
+
# The directives begins with a percent (%) character. Any text not listed
|
226
|
+
# as a directive will be passed through to the output string.
|
227
|
+
#
|
228
|
+
# The directive consists of a percent (%) character, zero or more flags,
|
229
|
+
# optional minimum field width and a conversion specifier as follows.
|
230
|
+
#
|
231
|
+
# %<flags><width><conversion>
|
232
|
+
#
|
233
|
+
# Flags:
|
234
|
+
#
|
235
|
+
# - don't pad a numerical output.
|
236
|
+
# _ use spaces for padding.
|
237
|
+
# 0 use zeros for padding.
|
238
|
+
# ^ upcase the result string.
|
239
|
+
# # change case.
|
240
|
+
#
|
241
|
+
# The minimum field width specifies the minimum width.
|
242
|
+
#
|
243
|
+
# Format directives:
|
244
|
+
#
|
245
|
+
# Date (Year, Month, Day):
|
246
|
+
# %Y - Year with century (can be negative)
|
247
|
+
# -0001, 0000, 1995, 2009, 14292, etc.
|
248
|
+
# %C - year / 100 (round down. 20 in 2009)
|
249
|
+
# %y - year % 100 (00..99)
|
250
|
+
#
|
251
|
+
# %m - Month of the year, zero-padded (01..12)
|
252
|
+
# %_m blank-padded ( 1..12)
|
253
|
+
# %-m no-padded (1..12)
|
254
|
+
#
|
255
|
+
# %d - Day of the month, zero-padded (01..30)
|
256
|
+
# %-d no-padded (1..30)
|
257
|
+
# %e - Day of the month, blank-padded ( 1..30)
|
258
|
+
#
|
259
|
+
# %j - Day of the year (001..360)
|
260
|
+
#
|
261
|
+
# Time (Hour, Minute, Second, Subsecond):
|
262
|
+
# %H - Hour of the day, 24-hour clock, zero-padded (00..23)
|
263
|
+
# %k - Hour of the day, 24-hour clock, blank-padded ( 0..23)
|
264
|
+
#
|
265
|
+
# %M - Minute of the hour (00..59)
|
266
|
+
#
|
267
|
+
# %S - Second of the minute (00..59)
|
268
|
+
#
|
269
|
+
# %L - Millisecond of the second (000..999)
|
270
|
+
# %N - Fractional seconds digits, default is 6 digits (microsecond)
|
271
|
+
# %3N millisecond (3 digits)
|
272
|
+
# %6N microsecond (6 digits)
|
273
|
+
#
|
274
|
+
# Weekday:
|
275
|
+
# %A - The full weekday name (``Firesday'')
|
276
|
+
# %^A uppercased (``FIRESDAY'')
|
277
|
+
# %w - Day of the week (Firesday is 0, 0..7)
|
278
|
+
#
|
279
|
+
# Seconds since the Epoch:
|
280
|
+
# %s - Number of seconds since 0001-01-01 00:00:00
|
281
|
+
#
|
282
|
+
# Literal string:
|
283
|
+
# %n - Newline character (\n)
|
284
|
+
# %t - Tab character (\t)
|
285
|
+
# %% - Literal ``%'' character
|
286
|
+
#
|
287
|
+
# Combination:
|
288
|
+
# %F - The ISO 8601 date format (%Y-%m-%d)
|
289
|
+
# %X - Same as %T
|
290
|
+
# %R - 24-hour time (%H:%M)
|
291
|
+
# %T - 24-hour time (%H:%M:%S)
|
292
|
+
#
|
293
|
+
# @param [String] format the format string
|
294
|
+
# @return [String] formatted string
|
295
|
+
def strftime(format)
|
296
|
+
source = { 'Y' => @year, 'C' => @year / 100, 'y' => @year % 100,
|
297
|
+
'm' => @month, 'd' => @mday, 'e' => @mday, 'j' => @yday,
|
298
|
+
'H' => @hour, 'k' => @hour, 'M' => @min, 'S' => @sec, 'L' => @usec, 'N' => @usec,
|
299
|
+
'A' => @wday, 'w' => @wday, 's' => @time,
|
300
|
+
'n' => "\n", 't' => "\t", '%' => '%' }
|
301
|
+
default_padding = { 'e' => ' ', 'k' => ' ', 'A' => ' ', 'n' => ' ', 't' => ' ', '%' => ' ' }
|
302
|
+
default_padding.default = '0'
|
303
|
+
default_width = { 'y' => 2, 'm' => 2, 'd' => 2, 'e' => 2, 'H' => 2, 'k' => 2, 'M' => 2, 'S' => 2,
|
304
|
+
'j' => 3, 'L' => 3,
|
305
|
+
'N' => 6 }
|
306
|
+
default_width.default = 0
|
307
|
+
|
308
|
+
format.gsub(/%([-_0^#]+)?(\d+)?([FXRT])/) {
|
309
|
+
case $3
|
310
|
+
when 'F' then '%Y-%m-%d'
|
311
|
+
when 'T', 'X' then '%H:%M:%S'
|
312
|
+
when 'R' then '%H:%M'
|
313
|
+
end
|
314
|
+
}.gsub(/%([-_0^#]+)?(\d+)?([YCymdejHkMSLNAawsnt%])/) {|s|
|
315
|
+
flags = $1; width = $2.to_i; conversion = $3; upcase = false
|
316
|
+
padding = default_padding[conversion]
|
317
|
+
width = default_width[conversion] if width.zero?
|
318
|
+
v = source[conversion]
|
319
|
+
|
320
|
+
flags.each_char {|c|
|
321
|
+
case c
|
322
|
+
when '-' then padding = nil
|
323
|
+
when '_' then padding = ' '
|
324
|
+
when '0' then padding = '0'
|
325
|
+
when '^', '#' then upcase = true
|
326
|
+
end
|
327
|
+
} if flags
|
328
|
+
|
329
|
+
case conversion
|
330
|
+
when 'L', 'N'
|
331
|
+
if (width <= 6)
|
332
|
+
v = v / (100000 / (10 ** (width - 1)))
|
333
|
+
else
|
334
|
+
v = v * (10 ** (width - 6))
|
335
|
+
end
|
336
|
+
when 'A'
|
337
|
+
v = Vanadiel::Day::DAYNAMES[v]
|
338
|
+
end
|
339
|
+
|
340
|
+
v = v.to_s
|
341
|
+
if width > 0 && padding && v.length < width
|
342
|
+
v = (padding * (width - v.length)) + v
|
343
|
+
end
|
344
|
+
|
345
|
+
upcase ? v.upcase : v
|
346
|
+
}
|
347
|
+
end
|
348
|
+
|
349
|
+
# Adds some number of seconds (possibly fractional) to time and returns that value as a new time.
|
350
|
+
#
|
351
|
+
# @param [Integer, Float] sec seconds
|
352
|
+
# @return [Vanadiel::Time] new time
|
353
|
+
def +(sec)
|
354
|
+
self.class.at((@time + (sec * ONE_SECOND)) / ONE_SECOND)
|
355
|
+
end
|
356
|
+
|
357
|
+
# Returns a new time that represents the difference between two times,
|
358
|
+
# or subtracts the given number of seconds in numeric from time.
|
359
|
+
#
|
360
|
+
# @overload -(time)
|
361
|
+
# Returns a new time that represents the difference between two times.
|
362
|
+
# @param [::Time, Vanadiel::Time] other_time the other time object
|
363
|
+
# @return [Float] seconds that represents the difference
|
364
|
+
# @overload -(seconds)
|
365
|
+
# Subtracts the given number of seconds in numeric from time.
|
366
|
+
# @param [Integer, Float] sec seconds
|
367
|
+
# @return [Vanadiel::Time] new time
|
368
|
+
def -(time)
|
369
|
+
if time.is_a? ::Time
|
370
|
+
(@time.to_f - self.class.earth_to_vana(time.to_f * ONE_SECOND)) / ONE_SECOND
|
371
|
+
elsif time.is_a?(Vanadiel::Time)
|
372
|
+
(@time.to_f - time.time) / ONE_SECOND
|
373
|
+
elsif time.is_a?(Integer) || time.is_a?(Float)
|
374
|
+
self.class.at((@time / ONE_SECOND) - time)
|
375
|
+
else
|
376
|
+
raise ArgumentError, 'invalid argument'
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
# Compares time with other time.
|
381
|
+
#
|
382
|
+
# @param [Vanadiel::Time] other_time the other time
|
383
|
+
# @return [-1] if the time is earlier than the other time.
|
384
|
+
# @return [0] if the time is same as the other time.
|
385
|
+
# @return [1] if the time is later than the other time.
|
386
|
+
# @return [nil] if it cannot compare.
|
387
|
+
def <=>(other_time)
|
388
|
+
@time <=> other_time.time
|
389
|
+
end
|
390
|
+
|
391
|
+
# Returns the value of time as a floating point number of seconds since C.E. 0001-01-01 00:00:00.
|
392
|
+
#
|
393
|
+
# @return [Float] seconds
|
394
|
+
def to_i
|
395
|
+
@time / ONE_SECOND
|
396
|
+
end
|
397
|
+
|
398
|
+
# Returns the value of time as an integer number of seconds since C.E. 0001-01-01 00:00:00.
|
399
|
+
#
|
400
|
+
# @return [Integer] seconds
|
401
|
+
def to_f
|
402
|
+
@time.to_f / ONE_SECOND
|
403
|
+
end
|
404
|
+
|
405
|
+
# Returns a string representing time. Equivalent to calling #strftime with
|
406
|
+
# a format string of "%Y-%m-%d %H:%M:%S".
|
407
|
+
#
|
408
|
+
# @return [String] the string representing time
|
409
|
+
def to_s
|
410
|
+
self.strftime('%Y-%m-%d %H:%M:%S')
|
411
|
+
end
|
412
|
+
|
413
|
+
# Returns the value of time as the Earth time object.
|
414
|
+
#
|
415
|
+
# @return [::Time] the Earth time object
|
416
|
+
def to_earth_time
|
417
|
+
::Time.at(self.class.vana_to_earth(@time) / ONE_SECOND)
|
418
|
+
end
|
419
|
+
|
420
|
+
# Returns a hash code for this time object.
|
421
|
+
#
|
422
|
+
# @return [Fixnum] the hash code
|
423
|
+
def hash; @time.hash ^ self.class.hash; end
|
424
|
+
|
425
|
+
# Returns true if time and other time are the same time.
|
426
|
+
#
|
427
|
+
# @return [Boolean] true if same
|
428
|
+
def ==(other); @time == other.time; end
|
429
|
+
|
430
|
+
# Returns true if time and other time are both Vanadiel::Time objects with the same time.
|
431
|
+
#
|
432
|
+
# @return [Boolean] true if same
|
433
|
+
def eql?(other); self.hash == other.hash; end
|
434
|
+
|
435
|
+
# Manually sets the time and recompute all fields.
|
436
|
+
#
|
437
|
+
# @param [Integer] time an integer number of microseconds
|
438
|
+
# @note This accessor is used internally.
|
439
|
+
def time=(time)
|
440
|
+
@time = time
|
441
|
+
compute_fields
|
442
|
+
end
|
443
|
+
|
444
|
+
def marshal_dump
|
445
|
+
@time
|
446
|
+
end
|
447
|
+
|
448
|
+
def marshal_load(obj)
|
449
|
+
self.time = obj
|
450
|
+
end
|
451
|
+
|
452
|
+
# Converts to the value of time as an integer number of microseconds since C.E. 0001-01-01 00:00:00.
|
453
|
+
#
|
454
|
+
# @param [Integer] year the year part (1..n)
|
455
|
+
# @param [Integer] mon the month part (1..12)
|
456
|
+
# @param [Integer] day the day of month part (1..30)
|
457
|
+
# @param [Integer] hour the hour part (0..23)
|
458
|
+
# @param [Integer] min the minute part (0..59)
|
459
|
+
# @param [Integer] sec the second part (0..59)
|
460
|
+
# @param [Integer] usec the microsecond part (0..999999)
|
461
|
+
# @return [Integer] microseconds as Vana'diel time
|
462
|
+
def self.ymdhms_to_usec(year, mon = 1, day = 1, hour = 0, min = 0, sec = 0, usec = 0)
|
463
|
+
raise ArgumentError, 'year out of range' if year < 0
|
464
|
+
raise ArgumentError, 'mon out of range' if mon < 1 || mon > 12
|
465
|
+
raise ArgumentError, 'day out of range' if day < 1 || day > 30
|
466
|
+
raise ArgumentError, 'hour out of range' if hour < 0 || hour > 23
|
467
|
+
raise ArgumentError, 'min out of range' if min < 0 || min > 59
|
468
|
+
raise ArgumentError, 'sec out of range' if sec < 0 || sec > 59
|
469
|
+
raise ArgumentError, 'usec out of range' if usec < 0 || usec > 999999
|
470
|
+
((year - 1) * ONE_YEAR) + ((mon - 1) * ONE_MONTH) + ((day - 1) * ONE_DAY) + (hour * ONE_HOUR) + (min * ONE_MINUTE) + (sec * ONE_SECOND) + usec
|
471
|
+
end
|
472
|
+
|
473
|
+
private
|
474
|
+
|
475
|
+
# Computes fields by its value of time.
|
476
|
+
def compute_fields
|
477
|
+
@year = (@time / ONE_YEAR).floor + 1
|
478
|
+
@month = (@time % ONE_YEAR / ONE_MONTH).floor + 1
|
479
|
+
@mday = (@time % ONE_MONTH / ONE_DAY).floor + 1
|
480
|
+
@hour = (@time % ONE_DAY / ONE_HOUR).floor
|
481
|
+
@min = (@time % ONE_HOUR / ONE_MINUTE).floor
|
482
|
+
@sec = (@time % ONE_MINUTE / ONE_SECOND).floor
|
483
|
+
@usec = (@time % ONE_SECOND).floor
|
484
|
+
|
485
|
+
@wday = (@time % ONE_WEEK / ONE_DAY).floor
|
486
|
+
@yday = ((@month - 1) * 30) + @mday
|
487
|
+
|
488
|
+
# MOON_BASE_TIME = 0 - (ONE_DAY * 12) # Start of New moon (10%)
|
489
|
+
#
|
490
|
+
# moon_time = @time - MOON_BASE_TIME
|
491
|
+
# @moon_age = (moon_time / ONE_DAY / 7 % (MAX_MOON_AGE + 1)).floor
|
492
|
+
# @time_of_moon = ((moon_time / ONE_DAY % 7) * ONE_DAY).floor
|
493
|
+
# + (@hour * ONE_HOUR)
|
494
|
+
# + (@min * ONE_MINUTE)
|
495
|
+
# + (@sec * ONE_SECOND)
|
496
|
+
# + (@usec)
|
497
|
+
|
498
|
+
# C.E. 0001/01/01 00:00:00 => WXC 19%
|
499
|
+
# C.E. 0886/01/01 00:00:00 => NM 10%
|
500
|
+
#
|
501
|
+
# 0% NM 7% WXC 40% FQM 57% WXG 90% FM 93% WNG 60% LQM 43% WNC 10% NM
|
502
|
+
# 2% NM 10% WXC 43% FQM 60% WXG 93% FM 90% WNG 57% LQM 40% WNC 7% NM
|
503
|
+
# 5% NM 12% WXC 45% FQM 62% WXG 95% FM 88% WNG 55% LQM 38% WNC 5% NM
|
504
|
+
# 14% WXC 48% FQM 64% WXG 98% FM 86% WNG 52% LQM 36% WNC 2% NM
|
505
|
+
# 17% WXC 50% FQM 67% WXG 100% FM 83% WNG 50% LQM 33% WNC
|
506
|
+
# 19% WXC 52% FQM 69% WXG 98% FM 81% WNG 48% LQM 31% WNC
|
507
|
+
# 21% WXC 55% FQM 71% WXG 95% FM 79% WNG 45% LQM 29% WNC
|
508
|
+
# 24% WXC 74% WXG 76% WNG 26% WNC
|
509
|
+
# 26% WXC 76% WXG 74% WNG 24% WNC
|
510
|
+
# 29% WXC 79% WXG 71% WNG 21% WNC
|
511
|
+
# 31% WXC 81% WXG 69% WNG 19% WNC
|
512
|
+
# 33% WXC 83% WXG 67% WNG 17% WNC
|
513
|
+
# 36% WXC 86% WXG 64% WNG 14% WNC
|
514
|
+
# 38% WXC 88% WXG 62% WNG 12% WNC
|
515
|
+
days = (@time / ONE_DAY).floor
|
516
|
+
@moon_percent = (((days + 8) % MOON_CYCLE_DAYS) * (200.0 / MOON_CYCLE_DAYS)).round
|
517
|
+
@moon_percent = 200 - @moon_percent if @moon_percent > 100
|
518
|
+
|
519
|
+
@moon_age = ((days + 12) / 7) % 12
|
520
|
+
@moon_age7 = case @moon_age
|
521
|
+
when 0 then 0
|
522
|
+
when 1, 2 then 1
|
523
|
+
when 3 then 2
|
524
|
+
when 4, 5 then 3
|
525
|
+
when 6 then 4
|
526
|
+
when 7, 8 then 5
|
527
|
+
when 9 then 6
|
528
|
+
when 10, 11 then 7
|
529
|
+
end
|
530
|
+
@time_of_moon = (((days + 12) % 7) * ONE_DAY) + (@hour * ONE_HOUR) + (@min * ONE_MINUTE) + (@sec * ONE_SECOND) + @usec
|
531
|
+
end
|
532
|
+
end
|
533
|
+
end
|