cowtech-extensions 2.1.3 → 2.5.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/.gitignore +1 -0
- data/.yardopts +1 -0
- data/README.md +10 -0
- data/Rakefile +6 -3
- data/cowtech-extensions.gemspec +9 -5
- data/doc/Cowtech.html +128 -0
- data/doc/Cowtech/Extensions.html +546 -0
- data/doc/Cowtech/Extensions/Boolean.html +297 -0
- data/doc/Cowtech/Extensions/DateTime.html +787 -0
- data/doc/Cowtech/Extensions/DateTime/ClassMethods.html +1592 -0
- data/doc/Cowtech/Extensions/Exceptions.html +125 -0
- data/doc/Cowtech/Extensions/Exceptions/Dump.html +133 -0
- data/doc/Cowtech/Extensions/Hash.html +393 -0
- data/doc/Cowtech/Extensions/Math.html +130 -0
- data/doc/Cowtech/Extensions/Math/ClassMethods.html +362 -0
- data/doc/Cowtech/Extensions/Object.html +1565 -0
- data/doc/Cowtech/Extensions/Pathname.html +225 -0
- data/doc/Cowtech/Extensions/Settings.html +1249 -0
- data/doc/Cowtech/Extensions/String.html +471 -0
- data/doc/Cowtech/Extensions/TimeZone.html +1210 -0
- data/doc/Cowtech/Extensions/TimeZone/ClassMethods.html +925 -0
- data/doc/Cowtech/Extensions/Version.html +189 -0
- data/doc/_index.html +305 -0
- data/doc/class_list.html +53 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +328 -0
- data/doc/file.README.html +103 -0
- data/doc/file_list.html +55 -0
- data/doc/frames.html +28 -0
- data/doc/index.html +103 -0
- data/doc/js/app.js +214 -0
- data/doc/js/full_list.js +173 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +620 -0
- data/doc/top-level-namespace.html +112 -0
- data/lib/cowtech-extensions.rb +47 -16
- data/lib/cowtech-extensions/boolean.rb +8 -1
- data/lib/cowtech-extensions/datetime.rb +377 -71
- data/lib/cowtech-extensions/exceptions.rb +16 -0
- data/lib/cowtech-extensions/hash.rb +20 -9
- data/lib/cowtech-extensions/math.rb +15 -8
- data/lib/cowtech-extensions/object.rb +84 -27
- data/lib/cowtech-extensions/pathname.rb +10 -1
- data/lib/cowtech-extensions/settings.rb +120 -0
- data/lib/cowtech-extensions/string.rb +30 -3
- data/lib/cowtech-extensions/version.rb +11 -2
- data/spec/coverage_helper.rb +19 -0
- data/spec/cowtech-extensions/boolean_spec.rb +4 -0
- data/spec/cowtech-extensions/datetime_spec.rb +238 -79
- data/spec/cowtech-extensions/hash_spec.rb +5 -2
- data/spec/cowtech-extensions/math_spec.rb +14 -4
- data/spec/cowtech-extensions/object_spec.rb +19 -1
- data/spec/cowtech-extensions/pathname_spec.rb +5 -1
- data/spec/cowtech-extensions/settings_spec.rb +101 -0
- data/spec/cowtech-extensions/string_spec.rb +13 -0
- data/spec/cowtech-extensions_spec.rb +33 -13
- data/spec/spec_helper.rb +2 -5
- metadata +182 -97
- data/lib/cowtech-extensions/utils.rb +0 -74
@@ -0,0 +1,112 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
6
|
+
<title>
|
7
|
+
Top Level Namespace
|
8
|
+
|
9
|
+
— Documentation by YARD 0.8.2.1
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
|
16
|
+
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
18
|
+
hasFrames = window.top.frames.main ? true : false;
|
19
|
+
relpath = '';
|
20
|
+
framesUrl = "frames.html#!" + escape(window.location.href);
|
21
|
+
</script>
|
22
|
+
|
23
|
+
|
24
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
25
|
+
|
26
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
27
|
+
|
28
|
+
|
29
|
+
</head>
|
30
|
+
<body>
|
31
|
+
<div id="header">
|
32
|
+
<div id="menu">
|
33
|
+
|
34
|
+
<a href="_index.html">Index</a> »
|
35
|
+
|
36
|
+
|
37
|
+
<span class="title">Top Level Namespace</span>
|
38
|
+
|
39
|
+
|
40
|
+
<div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
|
41
|
+
</div>
|
42
|
+
|
43
|
+
<div id="search">
|
44
|
+
|
45
|
+
<a class="full_list_link" id="class_list_link"
|
46
|
+
href="class_list.html">
|
47
|
+
Class List
|
48
|
+
</a>
|
49
|
+
|
50
|
+
<a class="full_list_link" id="method_list_link"
|
51
|
+
href="method_list.html">
|
52
|
+
Method List
|
53
|
+
</a>
|
54
|
+
|
55
|
+
<a class="full_list_link" id="file_list_link"
|
56
|
+
href="file_list.html">
|
57
|
+
File List
|
58
|
+
</a>
|
59
|
+
|
60
|
+
</div>
|
61
|
+
<div class="clear"></div>
|
62
|
+
</div>
|
63
|
+
|
64
|
+
<iframe id="search_frame"></iframe>
|
65
|
+
|
66
|
+
<div id="content"><h1>Top Level Namespace
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
</h1>
|
71
|
+
|
72
|
+
<dl class="box">
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
</dl>
|
82
|
+
<div class="clear"></div>
|
83
|
+
|
84
|
+
<h2>Defined Under Namespace</h2>
|
85
|
+
<p class="children">
|
86
|
+
|
87
|
+
|
88
|
+
<strong class="modules">Modules:</strong> <span class='object_link'><a href="Cowtech.html" title="Cowtech (module)">Cowtech</a></span>
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
</p>
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
</div>
|
104
|
+
|
105
|
+
<div id="footer">
|
106
|
+
Generated on Thu Jul 19 17:17:50 2012 by
|
107
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
108
|
+
0.8.2.1 (ruby-1.9.2).
|
109
|
+
</div>
|
110
|
+
|
111
|
+
</body>
|
112
|
+
</html>
|
data/lib/cowtech-extensions.rb
CHANGED
@@ -6,10 +6,12 @@
|
|
6
6
|
|
7
7
|
$KCODE='UTF8' if RUBY_VERSION < '1.9'
|
8
8
|
|
9
|
+
require "json"
|
9
10
|
require "active_support/all"
|
10
11
|
require "action_view"
|
11
12
|
|
12
|
-
require "cowtech-extensions/
|
13
|
+
require "cowtech-extensions/exceptions"
|
14
|
+
require "cowtech-extensions/settings"
|
13
15
|
require "cowtech-extensions/object"
|
14
16
|
require "cowtech-extensions/boolean"
|
15
17
|
require "cowtech-extensions/string"
|
@@ -18,12 +20,35 @@ require "cowtech-extensions/datetime"
|
|
18
20
|
require "cowtech-extensions/math"
|
19
21
|
require "cowtech-extensions/pathname"
|
20
22
|
|
23
|
+
# This is the top level module for Cowtech libraries.
|
21
24
|
module Cowtech
|
25
|
+
# Several Ruby object enhancements.
|
22
26
|
module Extensions
|
27
|
+
# Checks if we are running under Ruby 1.8
|
28
|
+
#
|
29
|
+
# @return [Boolean] `true` for Ruby 1.8, `false` otherwise.
|
30
|
+
def self.is_ruby_18?
|
31
|
+
RUBY_VERSION =~ /^1\.8/
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the settings for the extensions
|
35
|
+
#
|
36
|
+
# @return [Settings] The settings for the extensions.
|
23
37
|
def self.settings
|
24
|
-
Cowtech::Extensions::Settings.instance
|
38
|
+
::Cowtech::Extensions::Settings.instance
|
25
39
|
end
|
26
40
|
|
41
|
+
# Loads the extensions.
|
42
|
+
#
|
43
|
+
# @param what [Array] The modules to load. Valid values are:
|
44
|
+
# @option object Extensions for all objects.
|
45
|
+
# @option boolean Extensions for boolean values.
|
46
|
+
# @option string Extensions for strings.
|
47
|
+
# @option hash Extensions for hashs.
|
48
|
+
# @option datetime Extensions date and time objects.
|
49
|
+
# @option math Extensions for Math module.
|
50
|
+
# @option pathname Extensions for path objects.
|
51
|
+
# @return [Settings] The settings for the extensions.
|
27
52
|
def self.load!(*what)
|
28
53
|
what = ["object", "boolean", "string", "hash", "datetime", "math", "pathname"] if what.count == 0
|
29
54
|
what.collect! { |w| w.to_s }
|
@@ -32,51 +57,55 @@ module Cowtech
|
|
32
57
|
|
33
58
|
if what.include?("object") then
|
34
59
|
::Object.class_eval do
|
35
|
-
include Cowtech::Extensions::Object
|
60
|
+
include ::Cowtech::Extensions::Object
|
36
61
|
end
|
37
62
|
end
|
38
63
|
|
39
64
|
if what.include?("boolean") then
|
40
65
|
::TrueClass.class_eval do
|
41
|
-
include Cowtech::Extensions::Object
|
42
|
-
include Cowtech::Extensions::Boolean
|
66
|
+
include ::Cowtech::Extensions::Object
|
67
|
+
include ::Cowtech::Extensions::Boolean
|
43
68
|
end
|
44
69
|
|
45
70
|
::FalseClass.class_eval do
|
46
|
-
include Cowtech::Extensions::Object
|
47
|
-
include Cowtech::Extensions::Boolean
|
71
|
+
include ::Cowtech::Extensions::Object
|
72
|
+
include ::Cowtech::Extensions::Boolean
|
48
73
|
end
|
49
74
|
end
|
50
75
|
|
51
76
|
if what.include?("string") then
|
52
77
|
::String.class_eval do
|
53
|
-
include Cowtech::Extensions::String
|
78
|
+
include ::Cowtech::Extensions::String
|
54
79
|
end
|
55
80
|
end
|
56
81
|
|
57
82
|
if what.include?("hash") then
|
58
83
|
::Hash.class_eval do
|
59
|
-
include Cowtech::Extensions::Hash
|
84
|
+
include ::Cowtech::Extensions::Hash
|
60
85
|
end
|
61
86
|
end
|
62
87
|
|
63
88
|
if what.include?("datetime") then
|
64
89
|
::Time.class_eval do
|
65
|
-
include Cowtech::Extensions::DateTime
|
90
|
+
include ::Cowtech::Extensions::DateTime
|
66
91
|
end
|
67
92
|
|
68
93
|
::Date.class_eval do
|
69
|
-
include Cowtech::Extensions::DateTime
|
94
|
+
include ::Cowtech::Extensions::DateTime
|
70
95
|
end
|
71
96
|
|
72
97
|
::DateTime.class_eval do
|
73
|
-
include Cowtech::Extensions::DateTime
|
74
|
-
|
98
|
+
include ::Cowtech::Extensions::DateTime
|
99
|
+
end
|
100
|
+
|
101
|
+
::ActiveSupport::TimeZone.class_eval do
|
102
|
+
include ::Cowtech::Extensions::TimeZone
|
103
|
+
end
|
75
104
|
end
|
76
105
|
|
77
106
|
if what.include?("math") then
|
78
107
|
::Math.class_eval do
|
79
|
-
include Cowtech::Extensions::Math
|
108
|
+
include ::Cowtech::Extensions::Math
|
80
109
|
end
|
81
110
|
end
|
82
111
|
|
@@ -84,9 +113,11 @@ module Cowtech
|
|
84
113
|
require "pathname"
|
85
114
|
|
86
115
|
::Pathname.class_eval do
|
87
|
-
include Cowtech::Extensions::Pathname
|
116
|
+
include ::Cowtech::Extensions::Pathname
|
88
117
|
end
|
89
|
-
|
118
|
+
end
|
119
|
+
|
120
|
+
::Cowtech::Extensions::Settings.instance
|
90
121
|
end
|
91
122
|
end
|
92
123
|
end
|
@@ -6,13 +6,20 @@
|
|
6
6
|
|
7
7
|
module Cowtech
|
8
8
|
module Extensions
|
9
|
+
# Extension for the boolean values.
|
9
10
|
module Boolean
|
10
|
-
extend ActiveSupport::Concern
|
11
|
+
extend ::ActiveSupport::Concern
|
11
12
|
|
13
|
+
# Converts the boolean to an integer.
|
14
|
+
#
|
15
|
+
# @return [Fixnum] `1` for `true`, `0` for `false`.
|
12
16
|
def to_i
|
13
17
|
(self == true) ? 1 : 0
|
14
18
|
end
|
15
19
|
|
20
|
+
# Returns the boolean itself for use in form helpers.
|
21
|
+
#
|
22
|
+
# @return [Boolean] The boolean value.
|
16
23
|
def value
|
17
24
|
self
|
18
25
|
end
|
@@ -6,130 +6,216 @@
|
|
6
6
|
|
7
7
|
module Cowtech
|
8
8
|
module Extensions
|
9
|
+
# Extensions for date and time objects.
|
9
10
|
module DateTime
|
10
|
-
extend ActiveSupport::Concern
|
11
|
+
extend ::ActiveSupport::Concern
|
11
12
|
|
13
|
+
# General methods.
|
12
14
|
module ClassMethods
|
15
|
+
# Returns strings representations of days.
|
16
|
+
# @see Settings#setup_date_names
|
17
|
+
#
|
18
|
+
# @param short [Boolean] If return the abbreviated representations.
|
19
|
+
# @return [Array] Return string representations of days.
|
13
20
|
def days(short = true)
|
14
|
-
days = Cowtech::Extensions.settings.date_names[short ? :short_days : :long_days]
|
21
|
+
days = ::Cowtech::Extensions.settings.date_names[short ? :short_days : :long_days]
|
15
22
|
(1..7).to_a.collect { |i|
|
16
23
|
{:value => i.to_s, :label=> days[i - 1]}
|
17
24
|
}
|
18
25
|
|
19
26
|
end
|
20
27
|
|
28
|
+
# Returns strings representations of months.
|
29
|
+
# @see Settings#setup_date_names
|
30
|
+
#
|
31
|
+
# @param short [Boolean] If return the abbreviated representations.
|
32
|
+
# @return [Array] Return string representations of months.
|
21
33
|
def months(short = true)
|
22
|
-
months = Cowtech::Extensions.settings.date_names[short ? :short_months : :long_months]
|
34
|
+
months = ::Cowtech::Extensions.settings.date_names[short ? :short_months : :long_months]
|
23
35
|
(1..12).collect { |i|
|
24
36
|
{:value => i.to_s.rjust(2, "0"), :label=> months.at(i - 1)}
|
25
37
|
}
|
26
38
|
end
|
27
39
|
|
28
|
-
|
29
|
-
|
30
|
-
|
40
|
+
# Returns a range of years.
|
41
|
+
#
|
42
|
+
# ```ruby
|
43
|
+
# Date.years(3, false, 2010)
|
44
|
+
# # => [2007, 2008, 2009, 2010]
|
45
|
+
# ```
|
46
|
+
#
|
47
|
+
# ```ruby
|
48
|
+
# Date.years(1, true, 2010, true)
|
49
|
+
# # => [{:value=>2009, :label=>2009}, {:value=>2010, :label=>2010}, {:value=>2011, :label=>2011}]
|
50
|
+
# ```
|
51
|
+
#
|
52
|
+
#
|
53
|
+
# @param offset [Fixnum] The width of the range.
|
54
|
+
# @param also_future [Boolean] If return also future years.
|
55
|
+
# @param reference [Fixnum] The ending (or middle, if `also_future` is `true`) value of the range. Defaults to the current year.
|
56
|
+
# @param as_objects [Boolean] If to return years in hashes with `:value` and `label` keys.
|
57
|
+
# @return [Array] A range of years. Every entry is
|
58
|
+
def years(offset = 10, also_future = true, reference = nil, as_objects = false)
|
59
|
+
y = reference || ::Date.today.year
|
60
|
+
(y - offset..(also_future ? y + offset : y)).collect { |year| as_objects ? {:value => year, :label => year} : year }
|
31
61
|
end
|
32
62
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
63
|
+
# Returns all the availabe timezones.
|
64
|
+
#
|
65
|
+
# @return [Array]All the zone available.
|
66
|
+
def timezones
|
67
|
+
::ActiveSupport::TimeZone.all
|
68
|
+
end
|
37
69
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
70
|
+
# Returns a list of names of all timezones.
|
71
|
+
#
|
72
|
+
# @param with_dst [Boolean] If include DST version of the zones.
|
73
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(Daylight Saving Time)`.
|
74
|
+
# @return [Array] A list of names of timezones.
|
75
|
+
def list_timezones(with_dst = true, dst_label = nil)
|
76
|
+
::ActiveSupport::TimeZone.list_all(with_dst, dst_label)
|
77
|
+
end
|
42
78
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
79
|
+
# Find a zone by its name.
|
80
|
+
#
|
81
|
+
# @param name [String] The zone name.
|
82
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(Daylight Saving Time)`.
|
83
|
+
# @return [TimeZone] A timezone or `nil` if no zone was found.
|
84
|
+
def find_timezone(name = true, dst_label = nil)
|
85
|
+
::ActiveSupport::TimeZone.find(name, dst_label)
|
86
|
+
end
|
49
87
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
88
|
+
# Returns a string representation of a timezone.
|
89
|
+
#
|
90
|
+
# ```ruby
|
91
|
+
# DateTime.parameterize_zone(ActiveSupport::TimeZone["Pacific Time (US & Canada)"])
|
92
|
+
# # => "-0800@pacific-time-us-canada"
|
93
|
+
# ```
|
94
|
+
# @param tz [TimeZone] The zone to represent.
|
95
|
+
# @param with_offset [Boolean] If to include offset into the representation.
|
96
|
+
# @return [String] A string representation which can be used for searches.
|
97
|
+
def parameterize_zone(tz, with_offset = true)
|
98
|
+
::ActiveSupport::TimeZone::parameterize_zone(tz, with_offset)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Finds a parameterized timezone.
|
102
|
+
# @see DateTime#parameterize_zone
|
103
|
+
#
|
104
|
+
# @param tz [String] The zone to unparameterize.
|
105
|
+
# @param as_string [Boolean] If return just the zone name.
|
106
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(Daylight Saving Time)`.
|
107
|
+
# @return [String|TimeZone] The found timezone or `nil` if the zone is not valid.
|
108
|
+
def unparameterize_zone(tz, as_string = false, dst_label = nil)
|
109
|
+
::ActiveSupport::TimeZone::unparameterize_zone(tz, as_string, dst_label)
|
110
|
+
end
|
56
111
|
|
57
|
-
|
112
|
+
# Returns an offset in rational value.
|
113
|
+
#
|
114
|
+
# @param offset [Fixnum] The offset to convert.
|
115
|
+
# @return [Rational] The converted offset.
|
116
|
+
def rationalize_offset(offset)
|
117
|
+
::ActiveSupport::TimeZone.rationalize_offset(offset)
|
58
118
|
end
|
59
119
|
|
120
|
+
# Returns the Easter (according to Gregorian calendar) date for the year.
|
121
|
+
# @see http://en.wikipedia.org/wiki/Computus#Anonymous_Gregorian_algorithm
|
122
|
+
#
|
123
|
+
# @param year [Fixnum] The year to compute the date for. Defaults to the current year.
|
124
|
+
# @return [Date] The Easter date for the year.
|
125
|
+
def easter(year = nil)
|
126
|
+
year = ::Date.today.year if !year.is_integer?
|
127
|
+
|
128
|
+
# Compute using Anonymouse Gregorian Algorithm: http://en.wikipedia.org/wiki/Computus#Anonymous_Gregorian_algorithm
|
129
|
+
a = year % 19
|
130
|
+
b = (year / 100.0).floor
|
131
|
+
c = year % 100
|
132
|
+
d = (b / 4.0).floor
|
133
|
+
e = b % 4
|
134
|
+
f = ((b + 8) / 25.0).floor
|
135
|
+
g = ((b - f + 1) / 3.0).floor
|
136
|
+
h = ((19 * a) + b - d - g + 15) % 30
|
137
|
+
i = (c / 4.0).floor
|
138
|
+
k = c % 4
|
139
|
+
l = (32 + (2 * e) + (2 * i) - h - k) % 7
|
140
|
+
m = ((a + (11 * h) + (22 * l)) / 451.0).floor
|
141
|
+
|
142
|
+
day = ((h + l - (7 * m) + 114) % 31) + 1
|
143
|
+
month = ((h + l - (7 * m) + 114) / 31.0).floor
|
144
|
+
::Date.civil(year, month, day)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Lookups a custom datetime format.
|
148
|
+
# @see Settings#setup_date_formats
|
149
|
+
#
|
150
|
+
# @param key [Symbol] The name of the format to search.
|
151
|
+
# @return [String] The format or the name itself (if the format has not been found).
|
60
152
|
def custom_format(key)
|
61
|
-
Cowtech::Extensions.settings.date_formats.fetch(key.to_sym, key).ensure_string
|
153
|
+
::Cowtech::Extensions.settings.date_formats.fetch(key.to_sym, key).ensure_string
|
62
154
|
end
|
63
155
|
|
156
|
+
# Checks if the date is valid against to a specific format.
|
157
|
+
# @see DateTime#custom_format
|
158
|
+
#
|
159
|
+
# @param value [String] The value to check.
|
160
|
+
# @param format [String] The format to check the value against.
|
161
|
+
# @return [Boolean] `true` if the value is valid against the format, `false` otherwise.
|
64
162
|
def is_valid?(value, format = "%F %T")
|
65
163
|
rv = true
|
66
164
|
|
67
165
|
format = self.custom_format(format)
|
68
166
|
|
69
167
|
begin
|
70
|
-
::DateTime.strptime(value, format)
|
168
|
+
::DateTime.strptime(value.ensure_string, format)
|
71
169
|
rescue => e
|
72
170
|
rv = false
|
73
171
|
end
|
74
172
|
|
75
173
|
rv
|
76
174
|
end
|
77
|
-
|
78
|
-
def rational_offset(tz = ::Time.zone)
|
79
|
-
Rational((tz.tzinfo.current_period.utc_offset / 3600), 24)
|
80
|
-
end
|
81
|
-
|
82
|
-
def parameterize_zone(tz)
|
83
|
-
tz = tz.to_s if !tz.is_a?(String)
|
84
|
-
|
85
|
-
if tz =~ /^(\([a-z]+([+-])(\d{2}):(\d{2})\)\s(.+))$/i then
|
86
|
-
"#{$2}#{$3}#{$4}@#{$5.parameterize}"
|
87
|
-
else
|
88
|
-
tz.parameterize
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def find_parameterized_zone(tz, as_string = false)
|
93
|
-
tz = Date.parameterize_zone(tz) if !tz.is_a?(String)
|
94
|
-
tz = tz.gsub(/^(.+\d{4}@)?/, "")
|
95
|
-
|
96
|
-
rv = catch(:zone) do
|
97
|
-
ActiveSupport::TimeZone::MAPPING.each_key do |zone|
|
98
|
-
throw(:zone, zone) if ::DateTime.parameterize_zone(zone) == tz
|
99
|
-
end
|
100
|
-
|
101
|
-
nil
|
102
|
-
end
|
103
|
-
|
104
|
-
if rv then
|
105
|
-
(as_string ? rv : ActiveSupport::TimeZone[rv])
|
106
|
-
else
|
107
|
-
nil
|
108
|
-
end
|
109
|
-
end
|
110
175
|
end
|
111
176
|
|
177
|
+
# Returns the UTC::Time representation of the current datetime.
|
178
|
+
#
|
179
|
+
# @return [UTC::Time] The UTC::Time representation of the current datetime.
|
112
180
|
def utc_time
|
113
181
|
ua = (self.respond_to?(:utc) ? self : self.to_datetime).utc
|
114
182
|
::Time.utc(ua.year, ua.month, ua.day, ua.hour, ua.min, ua.sec)
|
115
183
|
end
|
116
184
|
|
185
|
+
# Returns the number of months passed between the beginning of the base year and the current date.
|
186
|
+
#
|
187
|
+
# ```ruby
|
188
|
+
# DateTime.civil(2012, 6, 1).in_months(2011)
|
189
|
+
# # => 18
|
190
|
+
# ```
|
191
|
+
#
|
192
|
+
# @param base [DateTime] The base year to start computation from. Default to current year.
|
193
|
+
# @return [Fixnum] Returns the number of months passed between the beginning of the base year and the current date.
|
117
194
|
def in_months(base = nil)
|
118
|
-
base ||= Date.today.year
|
195
|
+
base ||= ::Date.today.year
|
119
196
|
((self.year) - base) * 12 + self.month
|
120
197
|
end
|
121
198
|
|
199
|
+
# Returns the current month number with leading 0.
|
200
|
+
#
|
201
|
+
# @return [String] The current month number with leading 0.
|
122
202
|
def padded_month
|
123
203
|
self.month.to_s.rjust(2, "0")
|
124
204
|
end
|
125
205
|
|
206
|
+
# Formats a datetime, looking up also custom formats.
|
207
|
+
# @see Settings#setup_date_formats
|
208
|
+
#
|
209
|
+
# @param format [String] A format or a custom format name to use for formatting.
|
210
|
+
# @return [String] The formatted date.
|
126
211
|
def lstrftime(format = nil)
|
127
212
|
rv = nil
|
128
|
-
names = Cowtech::Extensions.settings.date_names
|
213
|
+
names = ::Cowtech::Extensions.settings.date_names
|
129
214
|
|
130
|
-
final_format = ::DateTime.custom_format(format).ensure_string.gsub(/(%{1,2}[abz])/i) do |match|
|
215
|
+
final_format = ::DateTime.custom_format(format).ensure_string.gsub(/(%{1,2}:?[abz])/i) do |match|
|
131
216
|
mrv = match
|
132
217
|
|
218
|
+
# Handling of %z is to fix ruby 1.8 bug in OSX: http://bugs.ruby-lang.org/issues/2396
|
133
219
|
if match !~ /^%%/ then
|
134
220
|
case match
|
135
221
|
when "%a"
|
@@ -140,28 +226,248 @@ module Cowtech
|
|
140
226
|
mrv = names[:short_months][self.month - 1]
|
141
227
|
when "%B"
|
142
228
|
mrv = names[:long_months][self.month - 1]
|
143
|
-
when "%Z"
|
144
|
-
mrv = self.formatted_offset(true) if RUBY_VERSION =~ /^1\.8/ # This is to fix ruby 1.8 bug in OSX
|
145
229
|
when "%z"
|
146
|
-
mrv = self.formatted_offset(false)
|
230
|
+
mrv = ::Cowtech::Extensions.is_ruby_18? ? self.formatted_offset(false) : nil
|
231
|
+
when "%:z"
|
232
|
+
mrv = ::Cowtech::Extensions.is_ruby_18? ? self.formatted_offset(true) : nil
|
147
233
|
end
|
148
|
-
|
149
|
-
mrv.sub!("%", "%%")
|
150
234
|
end
|
151
235
|
|
152
|
-
mrv
|
236
|
+
mrv ? mrv.sub("%", "%%") : match
|
153
237
|
end
|
154
238
|
|
155
239
|
self.strftime(final_format)
|
156
240
|
end
|
157
241
|
|
242
|
+
# Formats a datetime in the current timezone.
|
243
|
+
#
|
244
|
+
# @param format [String] The format to use for formatting.
|
245
|
+
# @return [String] The formatted date.
|
158
246
|
def local_strftime(format = nil)
|
159
247
|
(self.respond_to?(:in_time_zone) ? self.in_time_zone : self).strftime(::DateTime.custom_format(format))
|
160
248
|
end
|
161
249
|
|
250
|
+
# Formats a datetime in the current timezone, looking up also custom formats.
|
251
|
+
# @see Settings#setup_date_formats
|
252
|
+
#
|
253
|
+
# @param format [String] A format or a custom format name.
|
254
|
+
# @return [String] The formatted date.
|
162
255
|
def local_lstrftime(format = nil)
|
163
256
|
(self.respond_to?(:in_time_zone) ? self.in_time_zone : self).lstrftime(format)
|
164
257
|
end
|
165
258
|
end
|
259
|
+
|
260
|
+
# Extensions for timezone objects.
|
261
|
+
module TimeZone
|
262
|
+
extend ::ActiveSupport::Concern
|
263
|
+
|
264
|
+
# General methods.
|
265
|
+
module ClassMethods
|
266
|
+
# Returns an offset in rational value.
|
267
|
+
#
|
268
|
+
# @param offset [Fixnum] The offset to convert.
|
269
|
+
# @return [Rational] The converted offset.
|
270
|
+
def rationalize_offset(offset)
|
271
|
+
offset = offset.try(:offset) if !offset.is_a?(::Fixnum)
|
272
|
+
::TZInfo::OffsetRationals.rational_for_offset(offset.to_integer)
|
273
|
+
end
|
274
|
+
|
275
|
+
# Returns a +HH:MM formatted representation of the offset.
|
276
|
+
#
|
277
|
+
# @param offset [Rational|Fixnum] The offset to represent, in seconds or as a rational.
|
278
|
+
# @param colon [Boolean] If to put the colon in the output string.
|
279
|
+
# @return [String] The formatted offset.
|
280
|
+
def format_offset(offset, colon = true)
|
281
|
+
offset = (offset * 86400).to_i if offset.is_a?(::Rational)
|
282
|
+
offset.is_a?(::Fixnum) ? self.seconds_to_utc_offset(offset, colon) : nil
|
283
|
+
end
|
284
|
+
|
285
|
+
# Find a zone by its name.
|
286
|
+
#
|
287
|
+
# @param name [String] The zone name.
|
288
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(Daylight Saving Time)`.
|
289
|
+
# @return [TimeZone] A timezone or `nil` if no zone was found.
|
290
|
+
def find(name, dst_label = nil)
|
291
|
+
catch(:zone) do
|
292
|
+
::ActiveSupport::TimeZone.all.each do |zone|
|
293
|
+
throw(:zone, zone) if [zone.to_s, zone.to_s_with_dst(dst_label)].include?(name)
|
294
|
+
end
|
295
|
+
|
296
|
+
nil
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# Returns a list of names of all timezones.
|
301
|
+
#
|
302
|
+
# @param with_dst [Boolean] If include DST version of the zones.
|
303
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(Daylight Saving Time)`.
|
304
|
+
# @return [Array] A list of names of timezones.
|
305
|
+
def list_all(with_dst = true, dst_label = nil)
|
306
|
+
dst_key = "DST-#{dst_label}"
|
307
|
+
@zones_names ||= { "STANDARD" => ActiveSupport::TimeZone.all.collect(&:to_s) }
|
308
|
+
|
309
|
+
if with_dst && @zones_names[dst_key].blank? then
|
310
|
+
@zones_names[dst_key] = []
|
311
|
+
|
312
|
+
::ActiveSupport::TimeZone.all.each do |zone|
|
313
|
+
@zones_names[dst_key] << zone.to_s
|
314
|
+
@zones_names[dst_key] << zone.to_s_with_dst(dst_label)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
@zones_names[with_dst ? dst_key : "STANDARD"]
|
319
|
+
end
|
320
|
+
|
321
|
+
# Returns a string representation of a timezone.
|
322
|
+
#
|
323
|
+
# ```ruby
|
324
|
+
# DateTime.parameterize_zone(ActiveSupport::TimeZone["Pacific Time (US & Canada)"])
|
325
|
+
# # => "-0800@pacific-time-us-canada"
|
326
|
+
# ```
|
327
|
+
# @param tz [TimeZone] The zone to represent.
|
328
|
+
# @param with_offset [Boolean] If to include offset into the representation.
|
329
|
+
# @return [String] A string representation which can be used for searches.
|
330
|
+
def parameterize_zone(tz, with_offset = true)
|
331
|
+
tz = tz.to_s if !tz.is_a?(::String)
|
332
|
+
|
333
|
+
if tz =~ /^(\([a-z]+([+-])(\d{2})(:?)(\d{2})\)\s(.+))$/i then
|
334
|
+
with_offset ? "#{$2}#{$3}#{$5}@#{$6.parameterize}" : $6.parameterize
|
335
|
+
elsif !with_offset then
|
336
|
+
tz.gsub(/^([+-]?(\d{2})(:?)(\d{2})@)/, "")
|
337
|
+
else
|
338
|
+
tz.parameterize
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
# Finds a parameterized timezone.
|
343
|
+
# @see DateTime#parameterize_zone
|
344
|
+
#
|
345
|
+
# @param tz [String] The zone to unparameterize.
|
346
|
+
# @param as_string [Boolean] If return just the zone name.
|
347
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(Daylight Saving Time)`.
|
348
|
+
# @return [String|TimeZone] The found timezone or `nil` if the zone is not valid.
|
349
|
+
def unparameterize_zone(tz, as_string = false, dst_label = nil)
|
350
|
+
tz = self.parameterize_zone(tz, false)
|
351
|
+
|
352
|
+
rv = catch(:zone) do
|
353
|
+
self.list_all(true, dst_label).each do |zone|
|
354
|
+
throw(:zone, zone) if self.parameterize_zone(zone, false) == tz
|
355
|
+
end
|
356
|
+
|
357
|
+
nil
|
358
|
+
end
|
359
|
+
|
360
|
+
if rv then
|
361
|
+
(as_string ? rv : self.find(rv, dst_label))
|
362
|
+
else
|
363
|
+
nil
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
# Returns the current offset for this timezone, taking care of DST (Daylight Saving Time).
|
369
|
+
#
|
370
|
+
# @param rational [Boolean] If to return the offset as a Rational.
|
371
|
+
# @param date [DateTime] The date to consider. Defaults to now.
|
372
|
+
# @return [Fixnum|Rational] The offset of this timezone.
|
373
|
+
def current_offset(rational = false, date = nil)
|
374
|
+
date ||= ::DateTime.now
|
375
|
+
|
376
|
+
dst_period = self.dst_period
|
377
|
+
|
378
|
+
rv = (self.period_for_utc(date.utc).dst? ? self.dst_offset : self.offset)
|
379
|
+
rational ? self.class.rationalize_offset(rv) : rv
|
380
|
+
end
|
381
|
+
|
382
|
+
# Returns the standard offset for this timezone.
|
383
|
+
#
|
384
|
+
# @param rational [Boolean] If to return the offset as a Rational.
|
385
|
+
# @return [Fixnum|Rational] The offset of this timezone.
|
386
|
+
def offset(rational = false)
|
387
|
+
rv = self.utc_offset
|
388
|
+
rational ? self.class.rationalize_offset(rv) : rv
|
389
|
+
end
|
390
|
+
|
391
|
+
# Gets a period for this timezone when the DST (Daylight Saving Time) is active (it takes care of different hemispheres).
|
392
|
+
#
|
393
|
+
# @param year [Fixnum] The year to which refer to. Defaults to the current year.
|
394
|
+
# @return [TimezonePeriod] A period when the DST (Daylight Saving Time) is active or `nil` if the timezone doesn't use DST for that year.
|
395
|
+
def dst_period(year = nil)
|
396
|
+
year ||= ::Date.today.year
|
397
|
+
|
398
|
+
nothern_summer = ::DateTime.civil(year, 7, 15).utc # This is a representation of a summer period in the Northern Hemisphere.
|
399
|
+
southern_summer = ::DateTime.civil(year, 1, 15).utc # This is a representation of a summer period in the Northern Hemisphere.
|
400
|
+
|
401
|
+
period = self.period_for_utc(nothern_summer)
|
402
|
+
period = self.period_for_utc(southern_summer) if !period.dst?
|
403
|
+
period.dst? ? period : nil
|
404
|
+
end
|
405
|
+
|
406
|
+
# Checks if the timezone uses DST (Daylight Saving Time) for that year.
|
407
|
+
#
|
408
|
+
# @param year [Fixnum] The year to check. Defaults to the current year.
|
409
|
+
# @return [Boolean] `true` if the zone uses DST, `false` otherwise.
|
410
|
+
def uses_dst?(year = nil)
|
411
|
+
self.dst_period(year).present?
|
412
|
+
end
|
413
|
+
|
414
|
+
# Return the correction applied to the standard offset the timezone when the DST (Daylight Saving Time) is active.
|
415
|
+
#
|
416
|
+
# @param rational [Boolean] If to return the offset as a Rational.
|
417
|
+
# @param year [Fixnum] The year to which refer to. Defaults to the current year.
|
418
|
+
# @return [Fixnum|Rational] The correction for dst.
|
419
|
+
def dst_correction(rational = false, year = nil)
|
420
|
+
period = self.dst_period(year)
|
421
|
+
rv = period ? period.std_offset : 0
|
422
|
+
rational ? self.class.rationalize_offset(rv) : rv
|
423
|
+
end
|
424
|
+
|
425
|
+
# Returns the standard offset for this timezone timezone when the DST (Daylight Saving Time) is active.
|
426
|
+
#
|
427
|
+
# @param rational [Boolean] If to return the offset as a Rational.
|
428
|
+
# @param year [Fixnum] The year to which refer to. Defaults to the current year.
|
429
|
+
# @return [Fixnum|Rational] The DST offset for this timezone or `0` , if the timezone doesn't use DST for that year.
|
430
|
+
def dst_offset(rational = false, year = nil)
|
431
|
+
period = self.dst_period(year)
|
432
|
+
rv = period ? period.utc_total_offset : 0
|
433
|
+
rational ? self.class.rationalize_offset(rv) : rv
|
434
|
+
end
|
435
|
+
|
436
|
+
# Returns the name for this zone with DST (Daylight Saving Time) active.
|
437
|
+
#
|
438
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(Daylight Saving Time)`.
|
439
|
+
# @param year [Fixnum] The year to which refer to. Defaults to the current year.
|
440
|
+
# @return [String] The name for the zone with DST or `nil`, if the timezone doesn't use DST for that year.
|
441
|
+
def to_s_with_dst(dst_label = nil, year = nil)
|
442
|
+
dst_label ||= "(Daylight Saving Time)"
|
443
|
+
|
444
|
+
if self.uses_dst?(year) then
|
445
|
+
period = self.dst_period(year)
|
446
|
+
offset = self.class.seconds_to_utc_offset(period.utc_total_offset)
|
447
|
+
"(GMT#{offset}) #{name} #{dst_label}"
|
448
|
+
else
|
449
|
+
nil
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
# Returns the parametized name for this zone.
|
454
|
+
#
|
455
|
+
# @param with_offset [Boolean] If to include offset into the representation.
|
456
|
+
# @return [String] The parametized name for this zone.
|
457
|
+
def to_s_parameterized(with_offset = true)
|
458
|
+
::ActiveSupport::TimeZone.parameterize_zone(self.to_s, with_offset)
|
459
|
+
end
|
460
|
+
|
461
|
+
# Returns the parametized name for this zone with DST (Daylight Saving Time) active.
|
462
|
+
#
|
463
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(Daylight Saving Time)`.
|
464
|
+
# @param with_offset [Boolean] If to include offset into the representation.
|
465
|
+
# @param year [Fixnum] The year to which refer to. Defaults to the current year.
|
466
|
+
# @return [String] The parametized name for this zone with DST or `nil`, if the timezone doesn't use DST for that year.
|
467
|
+
def to_s_with_dst_parameterized(dst_label = nil, with_offset = true, year = nil)
|
468
|
+
rv = self.to_s_with_dst(dst_label, year)
|
469
|
+
rv ? ::ActiveSupport::TimeZone.parameterize_zone(rv) : nil
|
470
|
+
end
|
471
|
+
end
|
166
472
|
end
|
167
473
|
end
|