snafu 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/CHANGELOG.textile +12 -1
- data/README.textile +68 -7
- data/lib/snafu.rb +9 -2
- data/lib/snafu/achievements.rb +17 -0
- data/lib/snafu/client.rb +33 -23
- data/lib/snafu/giants.rb +35 -0
- data/lib/snafu/models.rb +4 -1
- data/lib/snafu/models/achievement.rb +24 -0
- data/lib/snafu/models/giant.rb +21 -0
- data/lib/snafu/models/glitch_time.rb +116 -0
- data/lib/snafu/models/hub.rb +5 -2
- data/lib/snafu/models/location.rb +3 -3
- data/lib/snafu/models/street.rb +13 -5
- data/lib/snafu/util.rb +12 -0
- data/lib/snafu/version.rb +1 -1
- data/snafu.gemspec +2 -2
- data/spec/snafu/achievements_spec.rb +51 -0
- data/spec/snafu/client_spec.rb +37 -15
- data/spec/snafu/giants_spec.rb +60 -0
- data/spec/snafu/locations_spec.rb +33 -32
- data/spec/snafu/models/achievement_spec.rb +31 -0
- data/spec/snafu/models/giant_spec.rb +38 -0
- data/spec/snafu/models/glitch_image_spec.rb +7 -17
- data/spec/snafu/models/glitch_time_spec.rb +176 -0
- data/spec/snafu/models/hub_spec.rb +2 -2
- data/spec/snafu/models/street_spec.rb +1 -1
- data/spec/snafu/models/util_spec.rb +22 -0
- data/spec/snafu_spec.rb +4 -3
- data/spec/spec_helper.rb +17 -16
- metadata +46 -54
- data/spec/fixtures/vcr_cassettes/Snafu_Client/call_should_accept_a_hash_of_POST_arguments.yml +0 -39
- data/spec/fixtures/vcr_cassettes/Snafu_Client/call_should_automatically_pass_in_the_oauth_token_if.yml +0 -36
- data/spec/fixtures/vcr_cassettes/Snafu_Client/call_should_automatically_pass_in_the_oauth_token_if_authenticate.yml +0 -36
- data/spec/fixtures/vcr_cassettes/Snafu_Client/call_should_automatically_pass_in_the_oauth_token_if_authenticate_called_with_true.yml +0 -36
- data/spec/fixtures/vcr_cassettes/Snafu_Client/call_should_automatically_pass_in_the_oauth_token_if_called_with_authenticate.yml +0 -36
- data/spec/fixtures/vcr_cassettes/Snafu_Client/call_should_automatically_pass_in_the_oauth_token_if_called_with_authenticate_true.yml +0 -36
- data/spec/fixtures/vcr_cassettes/Snafu_Client/call_should_automatically_pass_in_the_oauth_token_if_called_with_true.yml +0 -36
- data/spec/fixtures/vcr_cassettes/Snafu_Client/call_should_raise_a_GlitchAPIError_if_receiving_an_unsucessful_response_from_the_Glitch_API.yml +0 -36
- data/spec/fixtures/vcr_cassettes/Snafu_Locations/get_hub_should_return_a_valid_hub_if_given_a_valid_Hub_ID.yml +0 -39
- data/spec/fixtures/vcr_cassettes/Snafu_Locations/get_hub_should_return_an_array_of_valid_street_information_if_given_a_valid_Hub_ID.yml +0 -39
- data/spec/fixtures/vcr_cassettes/Snafu_Locations/get_hubs_should_populated_the_returned_Hub_objects_with_an_id_and_name.yml +0 -39
- data/spec/fixtures/vcr_cassettes/Snafu_Locations/get_hubs_should_return_an_array_of_Hub_objects.yml +0 -39
- data/spec/fixtures/vcr_cassettes/Snafu_Locations/get_hubs_should_return_an_array_of_all_hubs.yml +0 -39
- data/spec/fixtures/vcr_cassettes/Snafu_Locations/get_street_should_return_a_complete_street_if_given_a_valid_street_ID.yml +0 -40
- data/spec/fixtures/vcr_cassettes/Snafu_Models_Hub/initialize_should_populate_values_if_given_the_raw_JSON_response_from_HTTParty.yml +0 -39
- data/spec/fixtures/vcr_cassettes/Snafu_Models_Hub/initialize_should_populate_values_if_given_the_raw_response_from_Glitch.yml +0 -39
- data/spec/fixtures/vcr_cassettes/Snafu_Models_Street/initialize_should_populate_values_if_given_the_raw_JSON_response_from_HTTParty.yml +0 -40
- data/spec/fixtures/vcr_cassettes/Snafu_Models_Street_new/should_populate_values_if_given_the_raw_JSON_response_from_HTTParty.yml +0 -40
- data/spec/fixtures/vcr_cassettes/calendar_getHoldays/valid_calendar.yml +0 -39
data/.gitignore
CHANGED
data/CHANGELOG.textile
CHANGED
@@ -1,8 +1,19 @@
|
|
1
|
+
h2. 0.2.0
|
2
|
+
|
3
|
+
* Hub#streets now contains an array of Street objects
|
4
|
+
* Support for in-game Date & Time
|
5
|
+
* Support for the "achievements.listAll" method
|
6
|
+
* Support for the "giants.list" method
|
7
|
+
* Support for the "giants.getFavor" method
|
8
|
+
|
1
9
|
h2. 0.1.2
|
2
|
-
|
10
|
+
|
11
|
+
* Glitch Locations (Hubs, Streets, etc.) may have strings or integers for their IDs. Street#id, and Hub#id now always returns a String
|
3
12
|
|
4
13
|
h2. 0.1.1
|
14
|
+
|
5
15
|
* Fixed an issue where Hub.new would not populate steet names when given the raw result from Glitch
|
6
16
|
|
7
17
|
h2. 0.1.0
|
18
|
+
|
8
19
|
* Initial release
|
data/README.textile
CHANGED
@@ -1,20 +1,65 @@
|
|
1
1
|
h1. Snafu
|
2
2
|
|
3
|
-
Snafu is a Ruby gem that provides an interface to the "
|
3
|
+
Snafu is a Ruby gem that provides an interface to the "API":http://api.glitch.com for "Glitch":http://glitch.com, a browser-based MMO created by "Tiny Speck":http://tinyspeck.com.
|
4
|
+
|
5
|
+
h2. API Support
|
6
|
+
|
7
|
+
h3. Currently Supported
|
8
|
+
|
9
|
+
* In-Game Time & Date (See the GlitchTime class for more info)
|
10
|
+
* Giants
|
11
|
+
** giants.list (Snafu::Giants#get_giants)
|
12
|
+
* Locations
|
13
|
+
** locations.getHubs (Snafu::Locations#get_hubs)
|
14
|
+
** locations.getStreets (Snafu::Locations#get_hub)
|
15
|
+
** locations.streetInfo (Snafu::Locations#get_street)
|
16
|
+
|
17
|
+
h3. Not Yet Supported
|
18
|
+
|
19
|
+
* Achievements
|
20
|
+
* Auctions
|
21
|
+
* Avatar
|
22
|
+
* Players
|
23
|
+
* Skills
|
4
24
|
|
5
25
|
h2. Usage
|
6
26
|
|
7
|
-
To get started, instantiate
|
27
|
+
To get started, instantiate the client with either no options or with the OAuth token of an authenticated user if 'identity' scope or higher is required.
|
8
28
|
|
9
29
|
<pre lang="ruby">
|
10
30
|
snafu = Snafu.new(:oauth_token => "your-oauth-token")
|
11
31
|
</pre>
|
12
32
|
|
13
|
-
Snafu currently does not support Glitch's OAuth authentication. There are other gems that support authenticating with Glitch
|
33
|
+
Snafu currently does not support Glitch's OAuth authentication. There are other gems that support authenticating with Glitch such as "OmniAuth":https://github.com/intridea/omniauth.
|
34
|
+
|
35
|
+
h3. In-Game Time & Date
|
14
36
|
|
15
|
-
|
37
|
+
Note that the hour, minute, day of week, day of year, and day of month are all zero-based.
|
16
38
|
|
17
|
-
|
39
|
+
To get the current in-game date and time:
|
40
|
+
|
41
|
+
<pre lang="ruby">
|
42
|
+
current_time = snafu.glitch_time
|
43
|
+
current_time.year
|
44
|
+
=> 20
|
45
|
+
current_time.month
|
46
|
+
=> "Spork"
|
47
|
+
current_time.day
|
48
|
+
=> "Hairday"
|
49
|
+
</pre>
|
50
|
+
|
51
|
+
h3. Giants
|
52
|
+
|
53
|
+
<pre lang="ruby">
|
54
|
+
# giants.list
|
55
|
+
giants = snafu.get_giants
|
56
|
+
giants.first.name
|
57
|
+
=> "Alph"
|
58
|
+
</pre>
|
59
|
+
|
60
|
+
h3. Locations
|
61
|
+
|
62
|
+
All locations.* methods are supported. Each method returns a Ruby object representing the returned data.
|
18
63
|
|
19
64
|
<pre lang="ruby">
|
20
65
|
# locations.*
|
@@ -23,9 +68,21 @@ Currently, only the locations.* methods are supported via helper methods. Each m
|
|
23
68
|
street = snafu.get_street(street_tsid) # "locations.streetInfo"
|
24
69
|
</pre>
|
25
70
|
|
26
|
-
|
71
|
+
h3. Achievements
|
72
|
+
|
73
|
+
<pre lang="ruby">
|
74
|
+
achievements = snafu.get_achievements # "achievements.listAll"
|
75
|
+
achievements.first.name
|
76
|
+
=> "1-Star Cuisinartist"
|
77
|
+
achievements.first.desc
|
78
|
+
=> "Whipped up 11 meals with an Awesome Pot"
|
79
|
+
</pre>
|
80
|
+
|
81
|
+
h3. Manual Method Calls
|
27
82
|
|
28
|
-
You can also receive raw data from the Glitch API by passing
|
83
|
+
You can also receive raw data from the Glitch API by passing any method name into #call and supplying any required parameters via an options hash. This returns a Hash representation of the JSON returned by Glitch.
|
84
|
+
|
85
|
+
For example, to manually call the Glitch *calendar.getholidays* method:
|
29
86
|
|
30
87
|
<pre lang="ruby">
|
31
88
|
snafu.call("calendar.getHolidays")
|
@@ -63,3 +120,7 @@ You can also receive raw data from the Glitch API by passing in any method as a
|
|
63
120
|
=> }
|
64
121
|
</pre>
|
65
122
|
|
123
|
+
h2. Credits
|
124
|
+
|
125
|
+
"Jeff Browning":http://github.com/jbrowning - Original author
|
126
|
+
"Lee Jensen":https://github.com/outerim - Contributions to GlitchTime
|
data/lib/snafu.rb
CHANGED
@@ -1,6 +1,13 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
|
1
3
|
require 'httparty'
|
2
4
|
|
3
5
|
require "snafu/version"
|
4
6
|
require "snafu/locations"
|
5
|
-
require "snafu/
|
6
|
-
require "snafu/
|
7
|
+
require "snafu/models"
|
8
|
+
require "snafu/achievements"
|
9
|
+
require "snafu/giants"
|
10
|
+
require "snafu/util"
|
11
|
+
|
12
|
+
# Must be required last
|
13
|
+
require "snafu/client"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Snafu
|
2
|
+
module Achievements
|
3
|
+
def get_achievements
|
4
|
+
result = []
|
5
|
+
response = self.call("achievements.listAll", :per_page => self.achievement_count)
|
6
|
+
response["items"].each do |achievement|
|
7
|
+
result << Models::Achievement.new(achievement[1])
|
8
|
+
end
|
9
|
+
result
|
10
|
+
end
|
11
|
+
|
12
|
+
def achievement_count
|
13
|
+
response = self.call("achievements.listAll")
|
14
|
+
response["total"]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/snafu/client.rb
CHANGED
@@ -9,12 +9,15 @@ module Snafu
|
|
9
9
|
# it's p-p-p-party time
|
10
10
|
include HTTParty
|
11
11
|
|
12
|
-
# include other classes & modules so they can be called on
|
12
|
+
# include other classes & modules so they can be called on self
|
13
13
|
include Snafu::Locations
|
14
|
-
|
14
|
+
include Snafu::Achievements
|
15
|
+
include Snafu::Giants
|
16
|
+
include Snafu::Util
|
17
|
+
|
15
18
|
base_uri API_URL
|
16
19
|
|
17
|
-
attr_accessor :oauth_token
|
20
|
+
attr_accessor :oauth_token, :last_request_result
|
18
21
|
|
19
22
|
def initialize(options={})
|
20
23
|
@oauth_token = options[:oauth_token]
|
@@ -30,39 +33,46 @@ module Snafu
|
|
30
33
|
# snafu = snafu.call("players.stats", :authenticate => true)
|
31
34
|
#
|
32
35
|
# Invalid method calls will raise a <tt>GlitchAPIError</tt>
|
33
|
-
|
34
36
|
def call(method, query_parameters={})
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
options[:query] = query_parameters
|
39
|
-
if options[:query].has_key?(:authenticate) && options[:query][:authenticate] == true
|
40
|
-
if self.oauth_token.nil?
|
41
|
-
raise GlitchAPIError.new("You cannot do an authenticated call without an oauth token")
|
42
|
-
end
|
37
|
+
unless method.is_a? String
|
38
|
+
raise ArgumentError.new("Method argument must be a string")
|
39
|
+
end
|
43
40
|
|
44
|
-
|
45
|
-
|
46
|
-
|
41
|
+
options = { :format => :json }
|
42
|
+
unless query_parameters.empty?
|
43
|
+
options[:query] = query_parameters
|
44
|
+
if options[:query].has_key?(:authenticate) && options[:query][:authenticate] == true
|
45
|
+
if self.oauth_token.nil?
|
46
|
+
raise GlitchAuthenticationError.new("You cannot perform an authenticated call without an oauth token")
|
47
47
|
end
|
48
|
+
|
49
|
+
# Replace the authenticate key with the oauth token
|
50
|
+
options[:query].delete(:authenticate)
|
51
|
+
options[:query].update(:oauth_token => @oauth_token)
|
48
52
|
end
|
49
|
-
request_uri = "/#{method}"
|
50
|
-
parse_response(self.class.get(request_uri, options))
|
51
|
-
else
|
52
|
-
raise ArgumentError.new("Method argument must be a string")
|
53
53
|
end
|
54
|
+
request_uri = "/#{method}"
|
55
|
+
parse_response(self.class.get(request_uri, options))
|
54
56
|
end
|
55
57
|
|
56
58
|
def parse_response(response)
|
57
|
-
if response["
|
58
|
-
raise
|
59
|
+
if response["error"] == "invalid_token"
|
60
|
+
raise GlitchAuthenticationError.new("Invalid Token")
|
61
|
+
elsif response["ok"] == 0
|
62
|
+
if response["error"] == "missing_scope"
|
63
|
+
raise GlitchAuthenticationError.new("The token supplied has insufficient scope for this API method")
|
64
|
+
elsif response["error"] == "not_authenticated"
|
65
|
+
raise GlitchAuthenticationError.new("This API method requires authentication and no OAuth token has been supplied")
|
66
|
+
else
|
67
|
+
raise GlitchAPIError.new(response["error"])
|
68
|
+
end
|
59
69
|
else
|
70
|
+
@last_request_result = response
|
60
71
|
response
|
61
72
|
end
|
62
73
|
end
|
63
74
|
end
|
64
75
|
|
65
|
-
|
66
|
-
|
67
76
|
class GlitchAPIError < StandardError;end
|
77
|
+
class GlitchAuthenticationError < StandardError;end
|
68
78
|
end
|
data/lib/snafu/giants.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Snafu
|
2
|
+
module Giants
|
3
|
+
|
4
|
+
# Accesses the "giants.list" method from the Glitch API and returns an array of the
|
5
|
+
# Giant information
|
6
|
+
def get_giants
|
7
|
+
giants = []
|
8
|
+
response = self.call("giants.list")
|
9
|
+
response["giants"].each do |short_name, long_name|
|
10
|
+
giants << Models::Giant.new(:name => long_name)
|
11
|
+
end
|
12
|
+
giants
|
13
|
+
end
|
14
|
+
|
15
|
+
# Accesses the "giants.getFavor" method from the Glitch API and returns an array of
|
16
|
+
# giants with their respective favor for the authenticated users
|
17
|
+
#
|
18
|
+
# Requires an OAuth token with *read* scope
|
19
|
+
#
|
20
|
+
def get_giants_favor
|
21
|
+
giants = []
|
22
|
+
reponse = self.call("giants.getFavor", :authenticate => true)
|
23
|
+
reponse["giants"].each do |giant_short_name, giant_values|
|
24
|
+
giants << Models::Giant.new(
|
25
|
+
:name => giant_values["name"],
|
26
|
+
:cur_favor => giant_values["cur_favor"],
|
27
|
+
:max_favor => giant_values["max_favor"],
|
28
|
+
:cur_daily_favor => giant_values["cur_daily_favor"],
|
29
|
+
:max_daily_favor => giant_values["max_daily_favor"]
|
30
|
+
)
|
31
|
+
end
|
32
|
+
giants
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/snafu/models.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
require 'snafu/models/glitch_image'
|
2
2
|
require 'snafu/models/location'
|
3
3
|
require 'snafu/models/hub'
|
4
|
-
require 'snafu/models/street'
|
4
|
+
require 'snafu/models/street'
|
5
|
+
require 'snafu/models/glitch_time'
|
6
|
+
require 'snafu/models/achievement'
|
7
|
+
require 'snafu/models/giant'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Snafu
|
2
|
+
module Models
|
3
|
+
class Achievement
|
4
|
+
attr_reader :name, :description, :url, :image_60, :image_180
|
5
|
+
alias_method :desc, :description
|
6
|
+
def initialize(options = {})
|
7
|
+
@name = options["name"]
|
8
|
+
@description = options["description"] || options["desc"]
|
9
|
+
@url = options["url"]
|
10
|
+
@image_60 = parse_image options["image_60"]
|
11
|
+
@image_180 = parse_image options["image_180"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse_image(image)
|
15
|
+
if image.is_a? String
|
16
|
+
return GlitchImage.new(url: image)
|
17
|
+
elsif image.is_a? GlitchImage
|
18
|
+
return image
|
19
|
+
end
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Snafu
|
2
|
+
module Models
|
3
|
+
# Defines a class for Glitch Giants
|
4
|
+
#
|
5
|
+
class Giant
|
6
|
+
attr_reader :name, :cur_favor, :max_favor, :cur_daily_favor, :max_daily_favor
|
7
|
+
|
8
|
+
alias_method :current_favor, :cur_favor
|
9
|
+
alias_method :current_daily_favor, :cur_daily_favor
|
10
|
+
|
11
|
+
def initialize(options={})
|
12
|
+
@name = options[:name] || options["name"]
|
13
|
+
@cur_favor = (options[:cur_favor] || options["cur_favor"] || 0).to_i
|
14
|
+
@max_favor = (options[:max_favor] || options["max_favor"] || 0).to_i
|
15
|
+
@cur_daily_favor = (options[:cur_daily_favor] || options["cur_daily_favor"] || 0).to_i
|
16
|
+
@max_daily_favor = (options[:max_daily_favor] || options["max_daily_favor"] || 0).to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Snafu
|
2
|
+
module Models
|
3
|
+
# Class representing a Glitch date and time
|
4
|
+
#
|
5
|
+
# there are 4435200 real seconds in a game year
|
6
|
+
# there are 115200 real seconds in a game week
|
7
|
+
# there are 14400 real seconds in a game day
|
8
|
+
# there are 600 real seconds in a game hour
|
9
|
+
# there are 10 real seconds in a game minute
|
10
|
+
#
|
11
|
+
class GlitchTime
|
12
|
+
class InvalidTimestampError < Exception; end
|
13
|
+
|
14
|
+
GLITCH_EPOCH = 1238562000
|
15
|
+
Y_SECS = 4435200
|
16
|
+
D_SECS = 14400
|
17
|
+
H_SECS = 600
|
18
|
+
M_SECS = 10
|
19
|
+
DAYS_IN_MONTH = [29, 3, 53, 17, 73, 19, 13, 37, 5, 47, 11, 1]
|
20
|
+
MONTH_NAMES = %w(Primuary Spork Bruise Candy Fever Junuary Septa Remember Doom Widdershins Eleventy Recurse)
|
21
|
+
DAY_NAMES = %w(Hairday Moonday Twoday Weddingday Theday Fryday Standday Fabday Recurse)
|
22
|
+
|
23
|
+
attr_reader :timestamp, :seconds_since_epoch
|
24
|
+
|
25
|
+
def initialize(new_timestamp = Time.now)
|
26
|
+
@timestamp = new_timestamp.to_i
|
27
|
+
raise InvalidTimestampError if @timestamp < GLITCH_EPOCH
|
28
|
+
@timestamp = timestamp
|
29
|
+
@seconds_since_epoch = @timestamp - GLITCH_EPOCH
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the number of years since the Glitch epoch
|
33
|
+
def year
|
34
|
+
(seconds_since_epoch / Y_SECS).to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the 0-based day of the current Glitch year
|
38
|
+
def day_of_year
|
39
|
+
(seconds_since_start_of_year / D_SECS).to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the 0-based month of the year
|
43
|
+
def month
|
44
|
+
running_days = -1
|
45
|
+
DAYS_IN_MONTH.each_with_index do |days, idx|
|
46
|
+
running_days += days
|
47
|
+
return idx if day_of_year <= running_days
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the name of the month
|
52
|
+
def name_of_month
|
53
|
+
MONTH_NAMES[self.month]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns the 0-based day of the month
|
57
|
+
def day_of_month
|
58
|
+
return self.day_of_year if self.month == 0
|
59
|
+
self.day_of_year - DAYS_IN_MONTH.slice(0, (month)).inject(:+)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the 0-based day of the week
|
63
|
+
def day_of_week
|
64
|
+
return -1 if day_of_year == 307
|
65
|
+
days_since_epoch % 8
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns the name of the day
|
69
|
+
def name_of_day
|
70
|
+
DAY_NAMES[day_of_week]
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the number of game days since epoch
|
74
|
+
def days_since_epoch
|
75
|
+
self.day_of_year + (307 * year)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the hour of the day
|
79
|
+
def hour
|
80
|
+
# seconds_since_start_of_day / H_SECS
|
81
|
+
(seconds_since_start_of_day / H_SECS).to_i
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns the minute of the hour
|
85
|
+
#
|
86
|
+
# == Options
|
87
|
+
#
|
88
|
+
# +:padded+ - If true, will return a zero-padded string if the minute value is less than 10
|
89
|
+
def minute(padded = false)
|
90
|
+
min = (seconds_since_start_of_hour / M_SECS).to_i
|
91
|
+
if padded && min < 10
|
92
|
+
min = "0#{min}"
|
93
|
+
end
|
94
|
+
min
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_s
|
98
|
+
"#{self.hour}:#{self.minute(padded: true)}, #{self.name_of_day} #{self.day_of_month + 1} of #{self.name_of_month}, year #{self.year}"
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
def seconds_since_start_of_year
|
103
|
+
seconds_since_epoch - (Y_SECS * self.year)
|
104
|
+
end
|
105
|
+
|
106
|
+
def seconds_since_start_of_day
|
107
|
+
seconds_since_start_of_year - (D_SECS * self.day_of_year)
|
108
|
+
end
|
109
|
+
|
110
|
+
def seconds_since_start_of_hour
|
111
|
+
seconds_since_start_of_day - (H_SECS * self.hour)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|