lazier 1.0.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 +6 -0
- data/.travis.yml +8 -0
- data/.yardopts +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +82 -0
- data/README.md +33 -0
- data/Rakefile +18 -0
- data/doc/Lazier.html +557 -0
- data/doc/Lazier/Boolean.html +297 -0
- data/doc/Lazier/DateTime.html +787 -0
- data/doc/Lazier/DateTime/ClassMethods.html +1592 -0
- data/doc/Lazier/Exceptions.html +125 -0
- data/doc/Lazier/Exceptions/Dump.html +133 -0
- data/doc/Lazier/Hash.html +393 -0
- data/doc/Lazier/Math.html +130 -0
- data/doc/Lazier/Math/ClassMethods.html +362 -0
- data/doc/Lazier/Object.html +1565 -0
- data/doc/Lazier/Pathname.html +225 -0
- data/doc/Lazier/Settings.html +1249 -0
- data/doc/Lazier/String.html +471 -0
- data/doc/Lazier/TimeZone.html +1675 -0
- data/doc/Lazier/TimeZone/ClassMethods.html +1055 -0
- data/doc/Lazier/Version.html +189 -0
- data/doc/_index.html +306 -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 +107 -0
- data/doc/file_list.html +55 -0
- data/doc/frames.html +28 -0
- data/doc/index.html +107 -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 +652 -0
- data/doc/top-level-namespace.html +112 -0
- data/lazier.gemspec +36 -0
- data/lib/lazier.rb +127 -0
- data/lib/lazier/boolean.rb +26 -0
- data/lib/lazier/datetime.rb +548 -0
- data/lib/lazier/exceptions.rb +14 -0
- data/lib/lazier/hash.rb +40 -0
- data/lib/lazier/math.rb +47 -0
- data/lib/lazier/object.rb +163 -0
- data/lib/lazier/pathname.rb +26 -0
- data/lib/lazier/settings.rb +118 -0
- data/lib/lazier/string.rb +54 -0
- data/lib/lazier/version.rb +24 -0
- data/spec/coverage_helper.rb +19 -0
- data/spec/cowtech-extensions/boolean_spec.rb +30 -0
- data/spec/cowtech-extensions/datetime_spec.rb +352 -0
- data/spec/cowtech-extensions/hash_spec.rb +30 -0
- data/spec/cowtech-extensions/math_spec.rb +41 -0
- data/spec/cowtech-extensions/object_spec.rb +231 -0
- data/spec/cowtech-extensions/pathname_spec.rb +21 -0
- data/spec/cowtech-extensions/settings_spec.rb +118 -0
- data/spec/cowtech-extensions/string_spec.rb +45 -0
- data/spec/lazier_spec.rb +57 -0
- data/spec/spec_helper.rb +16 -0
- metadata +292 -0
@@ -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="Lazier.html" title="Lazier (module)">Lazier</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 Wed Aug 1 08:57:55 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/lazier.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the lazier gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
require File.expand_path('../lib/lazier/version', __FILE__)
|
8
|
+
|
9
|
+
Gem::Specification.new do |gem|
|
10
|
+
gem.name = "lazier"
|
11
|
+
gem.version = Lazier::Version::STRING
|
12
|
+
gem.homepage = "http://github.com/ShogunPanda/lazier"
|
13
|
+
gem.summary = %q{Several Ruby object enhancements.}
|
14
|
+
gem.description = %q{Several Ruby object enhancements.}
|
15
|
+
gem.rubyforge_project = "lazier"
|
16
|
+
|
17
|
+
gem.authors = ["Shogun"]
|
18
|
+
gem.email = ["shogun_panda@me.com"]
|
19
|
+
|
20
|
+
gem.files = `git ls-files`.split($\)
|
21
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
22
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
23
|
+
gem.require_paths = ["lib"]
|
24
|
+
|
25
|
+
gem.add_dependency("json", "~> 1.7.0")
|
26
|
+
gem.add_dependency("actionpack", "~> 3.0")
|
27
|
+
gem.add_dependency("tzinfo", "~> 0.3.0")
|
28
|
+
|
29
|
+
gem.add_development_dependency("rspec", "~> 2.11.0")
|
30
|
+
gem.add_development_dependency("rake", "~> 0.9.0")
|
31
|
+
gem.add_development_dependency("simplecov", "~> 0.6.0")
|
32
|
+
gem.add_development_dependency("pry", ">= 0")
|
33
|
+
gem.add_development_dependency("yard", "~> 0.8.0")
|
34
|
+
gem.add_development_dependency("redcarpet", "~> 2.1.0")
|
35
|
+
gem.add_development_dependency("github-markup", "~> 0.7.0")
|
36
|
+
end
|
data/lib/lazier.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the lazier gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
$KCODE='UTF8' if RUBY_VERSION < '1.9'
|
8
|
+
|
9
|
+
require "json"
|
10
|
+
require "tzinfo"
|
11
|
+
require "active_support/all"
|
12
|
+
require "action_view"
|
13
|
+
|
14
|
+
require "lazier/version" if !defined?(Lazier::Version)
|
15
|
+
require "lazier/exceptions"
|
16
|
+
require "lazier/settings"
|
17
|
+
require "lazier/object"
|
18
|
+
require "lazier/boolean"
|
19
|
+
require "lazier/string"
|
20
|
+
require "lazier/hash"
|
21
|
+
require "lazier/datetime"
|
22
|
+
require "lazier/math"
|
23
|
+
require "lazier/pathname"
|
24
|
+
|
25
|
+
# Several Ruby object enhancements.
|
26
|
+
module Lazier
|
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.
|
37
|
+
def self.settings
|
38
|
+
::Lazier::Settings.instance
|
39
|
+
end
|
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.
|
52
|
+
def self.load!(*what)
|
53
|
+
what = ["object", "boolean", "string", "hash", "datetime", "math", "pathname"] if what.count == 0
|
54
|
+
what.collect! { |w| w.to_s }
|
55
|
+
|
56
|
+
# Dependency resolving
|
57
|
+
what << "object" if what.include?("datetime")
|
58
|
+
what << "object" if what.include?("math")
|
59
|
+
what.compact.uniq!
|
60
|
+
|
61
|
+
if what.include?("object") then
|
62
|
+
::Object.class_eval do
|
63
|
+
include ::Lazier::Object
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
if what.include?("boolean") then
|
68
|
+
::TrueClass.class_eval do
|
69
|
+
include ::Lazier::Object
|
70
|
+
include ::Lazier::Boolean
|
71
|
+
end
|
72
|
+
|
73
|
+
::FalseClass.class_eval do
|
74
|
+
include ::Lazier::Object
|
75
|
+
include ::Lazier::Boolean
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
if what.include?("string") then
|
80
|
+
::String.class_eval do
|
81
|
+
include ::Lazier::String
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
if what.include?("hash") then
|
86
|
+
::Hash.class_eval do
|
87
|
+
include ::Lazier::Hash
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
if what.include?("datetime") then
|
92
|
+
::Time.class_eval do
|
93
|
+
include ::Lazier::DateTime
|
94
|
+
end
|
95
|
+
|
96
|
+
::Date.class_eval do
|
97
|
+
include ::Lazier::DateTime
|
98
|
+
end
|
99
|
+
|
100
|
+
::DateTime.class_eval do
|
101
|
+
include ::Lazier::DateTime
|
102
|
+
end
|
103
|
+
|
104
|
+
::ActiveSupport::TimeZone.class_eval do
|
105
|
+
include ::Lazier::TimeZone
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
if what.include?("math") then
|
110
|
+
::Math.class_eval do
|
111
|
+
include ::Lazier::Math
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
if what.include?("pathname") then
|
116
|
+
require "pathname"
|
117
|
+
|
118
|
+
::Pathname.class_eval do
|
119
|
+
include ::Lazier::Pathname
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
yield if block_given?
|
124
|
+
|
125
|
+
::Lazier::Settings.instance
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the lazier gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Lazier
|
8
|
+
# Extension for the boolean values.
|
9
|
+
module Boolean
|
10
|
+
extend ::ActiveSupport::Concern
|
11
|
+
|
12
|
+
# Converts the boolean to an integer.
|
13
|
+
#
|
14
|
+
# @return [Fixnum] `1` for `true`, `0` for `false`.
|
15
|
+
def to_i
|
16
|
+
(self == true) ? 1 : 0
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the boolean itself for use in form helpers.
|
20
|
+
#
|
21
|
+
# @return [Boolean] The boolean value.
|
22
|
+
def value
|
23
|
+
self
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,548 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the lazier gem. Copyright (C) 2011 and above Shogun <shogun_panda@me.com>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Lazier
|
8
|
+
# Extensions for date and time objects.
|
9
|
+
module DateTime
|
10
|
+
extend ::ActiveSupport::Concern
|
11
|
+
|
12
|
+
# General methods.
|
13
|
+
module ClassMethods
|
14
|
+
# Returns strings representations of days.
|
15
|
+
# @see Settings#setup_date_names
|
16
|
+
#
|
17
|
+
# @param short [Boolean] If return the abbreviated representations.
|
18
|
+
# @return [Array] Return string representations of days.
|
19
|
+
def days(short = true)
|
20
|
+
days = ::Lazier.settings.date_names[short ? :short_days : :long_days]
|
21
|
+
(1..7).to_a.collect { |i|
|
22
|
+
{:value => i.to_s, :label=> days[i - 1]}
|
23
|
+
}
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns strings representations of months.
|
28
|
+
# @see Settings#setup_date_names
|
29
|
+
#
|
30
|
+
# @param short [Boolean] If return the abbreviated representations.
|
31
|
+
# @return [Array] Return string representations of months.
|
32
|
+
def months(short = true)
|
33
|
+
months = ::Lazier.settings.date_names[short ? :short_months : :long_months]
|
34
|
+
(1..12).collect { |i|
|
35
|
+
{:value => i.to_s.rjust(2, "0"), :label=> months.at(i - 1)}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns a range of years.
|
40
|
+
#
|
41
|
+
# ```ruby
|
42
|
+
# Date.years(3, false, 2010)
|
43
|
+
# # => [2007, 2008, 2009, 2010]
|
44
|
+
# ```
|
45
|
+
#
|
46
|
+
# ```ruby
|
47
|
+
# Date.years(1, true, 2010, true)
|
48
|
+
# # => [{:value=>2009, :label=>2009}, {:value=>2010, :label=>2010}, {:value=>2011, :label=>2011}]
|
49
|
+
# ```
|
50
|
+
#
|
51
|
+
#
|
52
|
+
# @param offset [Fixnum] The width of the range.
|
53
|
+
# @param also_future [Boolean] If return also future years.
|
54
|
+
# @param reference [Fixnum] The ending (or middle, if `also_future` is `true`) value of the range. Defaults to the current year.
|
55
|
+
# @param as_objects [Boolean] If to return years in hashes with `:value` and `label` keys.
|
56
|
+
# @return [Array] A range of years. Every entry is
|
57
|
+
def years(offset = 10, also_future = true, reference = nil, as_objects = false)
|
58
|
+
y = reference || ::Date.today.year
|
59
|
+
(y - offset..(also_future ? y + offset : y)).collect { |year| as_objects ? {:value => year, :label => year} : year }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns all the availabe timezones.
|
63
|
+
#
|
64
|
+
# @return [Array]All the zone available.
|
65
|
+
def timezones
|
66
|
+
::ActiveSupport::TimeZone.all
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns a list of names of all timezones.
|
70
|
+
#
|
71
|
+
# @param with_dst [Boolean] If include DST version of the zones.
|
72
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
|
73
|
+
# @return [Array] A list of names of timezones.
|
74
|
+
def list_timezones(with_dst = true, dst_label = nil)
|
75
|
+
::ActiveSupport::TimeZone.list_all(with_dst, dst_label)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Find a zone by its name.
|
79
|
+
#
|
80
|
+
# @param name [String] The zone name.
|
81
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
|
82
|
+
# @return [TimeZone] A timezone or `nil` if no zone was found.
|
83
|
+
def find_timezone(name = true, dst_label = nil)
|
84
|
+
::ActiveSupport::TimeZone.find(name, dst_label)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns a string representation of a timezone.
|
88
|
+
#
|
89
|
+
# ```ruby
|
90
|
+
# DateTime.parameterize_zone(ActiveSupport::TimeZone["Pacific Time (US & Canada)"])
|
91
|
+
# # => "-0800@pacific-time-us-canada"
|
92
|
+
# ```
|
93
|
+
# @param tz [TimeZone] The zone to represent.
|
94
|
+
# @param with_offset [Boolean] If to include offset into the representation.
|
95
|
+
# @return [String] A string representation which can be used for searches.
|
96
|
+
def parameterize_zone(tz, with_offset = true)
|
97
|
+
::ActiveSupport::TimeZone::parameterize_zone(tz, with_offset)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Finds a parameterized timezone.
|
101
|
+
# @see DateTime#parameterize_zone
|
102
|
+
#
|
103
|
+
# @param tz [String] The zone to unparameterize.
|
104
|
+
# @param as_string [Boolean] If return just the zone name.
|
105
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
|
106
|
+
# @return [String|TimeZone] The found timezone or `nil` if the zone is not valid.
|
107
|
+
def unparameterize_zone(tz, as_string = false, dst_label = nil)
|
108
|
+
::ActiveSupport::TimeZone::unparameterize_zone(tz, as_string, dst_label)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns an offset in rational value.
|
112
|
+
#
|
113
|
+
# @param offset [Fixnum] The offset to convert.
|
114
|
+
# @return [Rational] The converted offset.
|
115
|
+
def rationalize_offset(offset)
|
116
|
+
::ActiveSupport::TimeZone.rationalize_offset(offset)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns the Easter (according to Gregorian calendar) date for the year.
|
120
|
+
# @see http://en.wikipedia.org/wiki/Computus#Anonymous_Gregorian_algorithm
|
121
|
+
#
|
122
|
+
# @param year [Fixnum] The year to compute the date for. Defaults to the current year.
|
123
|
+
# @return [Date] The Easter date for the year.
|
124
|
+
def easter(year = nil)
|
125
|
+
year = ::Date.today.year if !year.is_integer?
|
126
|
+
|
127
|
+
# Compute using Anonymouse Gregorian Algorithm: http://en.wikipedia.org/wiki/Computus#Anonymous_Gregorian_algorithm
|
128
|
+
a = year % 19
|
129
|
+
b = (year / 100.0).floor
|
130
|
+
c = year % 100
|
131
|
+
d = (b / 4.0).floor
|
132
|
+
e = b % 4
|
133
|
+
f = ((b + 8) / 25.0).floor
|
134
|
+
g = ((b - f + 1) / 3.0).floor
|
135
|
+
h = ((19 * a) + b - d - g + 15) % 30
|
136
|
+
i = (c / 4.0).floor
|
137
|
+
k = c % 4
|
138
|
+
l = (32 + (2 * e) + (2 * i) - h - k) % 7
|
139
|
+
m = ((a + (11 * h) + (22 * l)) / 451.0).floor
|
140
|
+
|
141
|
+
day = ((h + l - (7 * m) + 114) % 31) + 1
|
142
|
+
month = ((h + l - (7 * m) + 114) / 31.0).floor
|
143
|
+
::Date.civil(year, month, day)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Lookups a custom datetime format.
|
147
|
+
# @see Settings#setup_date_formats
|
148
|
+
#
|
149
|
+
# @param key [Symbol] The name of the format to search.
|
150
|
+
# @return [String] The format or the name itself (if the format has not been found).
|
151
|
+
def custom_format(key)
|
152
|
+
::Lazier.settings.date_formats.fetch(key.to_sym, key).ensure_string
|
153
|
+
end
|
154
|
+
|
155
|
+
# Checks if the date is valid against to a specific format.
|
156
|
+
# @see DateTime#custom_format
|
157
|
+
#
|
158
|
+
# @param value [String] The value to check.
|
159
|
+
# @param format [String] The format to check the value against.
|
160
|
+
# @return [Boolean] `true` if the value is valid against the format, `false` otherwise.
|
161
|
+
def is_valid?(value, format = "%F %T")
|
162
|
+
rv = true
|
163
|
+
|
164
|
+
format = self.custom_format(format)
|
165
|
+
|
166
|
+
begin
|
167
|
+
::DateTime.strptime(value.ensure_string, format)
|
168
|
+
rescue => e
|
169
|
+
rv = false
|
170
|
+
end
|
171
|
+
|
172
|
+
rv
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Returns the UTC::Time representation of the current datetime.
|
177
|
+
#
|
178
|
+
# @return [UTC::Time] The UTC::Time representation of the current datetime.
|
179
|
+
def utc_time
|
180
|
+
ua = (self.respond_to?(:utc) ? self : self.to_datetime).utc
|
181
|
+
::Time.utc(ua.year, ua.month, ua.day, ua.hour, ua.min, ua.sec)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Returns the number of months passed between the beginning of the base year and the current date.
|
185
|
+
#
|
186
|
+
# ```ruby
|
187
|
+
# DateTime.civil(2012, 6, 1).in_months(2011)
|
188
|
+
# # => 18
|
189
|
+
# ```
|
190
|
+
#
|
191
|
+
# @param base [DateTime] The base year to start computation from. Default to current year.
|
192
|
+
# @return [Fixnum] Returns the number of months passed between the beginning of the base year and the current date.
|
193
|
+
def in_months(base = nil)
|
194
|
+
base ||= ::Date.today.year
|
195
|
+
((self.year) - base) * 12 + self.month
|
196
|
+
end
|
197
|
+
|
198
|
+
# Returns the current month number with leading 0.
|
199
|
+
#
|
200
|
+
# @return [String] The current month number with leading 0.
|
201
|
+
def padded_month
|
202
|
+
self.month.to_s.rjust(2, "0")
|
203
|
+
end
|
204
|
+
|
205
|
+
# Formats a datetime, looking up also custom formats.
|
206
|
+
# @see Settings#setup_date_formats
|
207
|
+
#
|
208
|
+
# @param format [String] A format or a custom format name to use for formatting.
|
209
|
+
# @return [String] The formatted date.
|
210
|
+
def lstrftime(format = nil)
|
211
|
+
rv = nil
|
212
|
+
names = ::Lazier.settings.date_names
|
213
|
+
|
214
|
+
final_format = ::DateTime.custom_format(format).ensure_string.gsub(/(%{1,2}:?[abz])/i) do |match|
|
215
|
+
mrv = match
|
216
|
+
|
217
|
+
# Handling of %z is to fix ruby 1.8 bug in OSX: http://bugs.ruby-lang.org/issues/2396
|
218
|
+
if match !~ /^%%/ then
|
219
|
+
case match
|
220
|
+
when "%a"
|
221
|
+
mrv = names[:short_days][self.wday]
|
222
|
+
when "%A"
|
223
|
+
mrv = names[:long_days][self.wday]
|
224
|
+
when "%b"
|
225
|
+
mrv = names[:short_months][self.month - 1]
|
226
|
+
when "%B"
|
227
|
+
mrv = names[:long_months][self.month - 1]
|
228
|
+
when "%z"
|
229
|
+
mrv = ::Lazier.is_ruby_18? ? self.formatted_offset(false) : nil
|
230
|
+
when "%:z"
|
231
|
+
mrv = ::Lazier.is_ruby_18? ? self.formatted_offset(true) : nil
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
mrv ? mrv.sub("%", "%%") : match
|
236
|
+
end
|
237
|
+
|
238
|
+
self.strftime(final_format)
|
239
|
+
end
|
240
|
+
|
241
|
+
# Formats a datetime in the current timezone.
|
242
|
+
#
|
243
|
+
# @param format [String] The format to use for formatting.
|
244
|
+
# @return [String] The formatted date.
|
245
|
+
def local_strftime(format = nil)
|
246
|
+
(self.respond_to?(:in_time_zone) ? self.in_time_zone : self).strftime(::DateTime.custom_format(format))
|
247
|
+
end
|
248
|
+
|
249
|
+
# Formats a datetime in the current timezone, looking up also custom formats.
|
250
|
+
# @see Settings#setup_date_formats
|
251
|
+
#
|
252
|
+
# @param format [String] A format or a custom format name.
|
253
|
+
# @return [String] The formatted date.
|
254
|
+
def local_lstrftime(format = nil)
|
255
|
+
(self.respond_to?(:in_time_zone) ? self.in_time_zone : self).lstrftime(format)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# Extensions for timezone objects.
|
260
|
+
module TimeZone
|
261
|
+
extend ::ActiveSupport::Concern
|
262
|
+
|
263
|
+
# General methods.
|
264
|
+
module ClassMethods
|
265
|
+
# Returns an offset in rational value.
|
266
|
+
#
|
267
|
+
# @param offset [Fixnum] The offset to convert.
|
268
|
+
# @return [Rational] The converted offset.
|
269
|
+
def rationalize_offset(offset)
|
270
|
+
offset = offset.try(:offset) if !offset.is_a?(::Fixnum)
|
271
|
+
::TZInfo::OffsetRationals.rational_for_offset(offset.to_integer)
|
272
|
+
end
|
273
|
+
|
274
|
+
# Returns a +HH:MM formatted representation of the offset.
|
275
|
+
#
|
276
|
+
# @param offset [Rational|Fixnum] The offset to represent, in seconds or as a rational.
|
277
|
+
# @param colon [Boolean] If to put the colon in the output string.
|
278
|
+
# @return [String] The formatted offset.
|
279
|
+
def format_offset(offset, colon = true)
|
280
|
+
offset = (offset * 86400).to_i if offset.is_a?(::Rational)
|
281
|
+
offset.is_a?(::Fixnum) ? self.seconds_to_utc_offset(offset, colon) : nil
|
282
|
+
end
|
283
|
+
|
284
|
+
# Find a zone by its name.
|
285
|
+
#
|
286
|
+
# @param name [String] The zone name.
|
287
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
|
288
|
+
# @return [TimeZone] A timezone or `nil` if no zone was found.
|
289
|
+
def find(name, dst_label = nil)
|
290
|
+
catch(:zone) do
|
291
|
+
::ActiveSupport::TimeZone.all.each do |zone|
|
292
|
+
zone.aliases.each do |zone_alias|
|
293
|
+
throw(:zone, zone) if [zone.to_str(zone_alias), zone.to_str_with_dst(dst_label, nil, zone_alias)].include?(name)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
nil
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# Returns a list of names of all timezones.
|
302
|
+
#
|
303
|
+
# @param with_dst [Boolean] If include DST version of the zones.
|
304
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
|
305
|
+
# @return [Array] A list of names of timezones.
|
306
|
+
def list_all(with_dst = true, dst_label = nil)
|
307
|
+
dst_label ||= "(DST)"
|
308
|
+
dst_key = "DST-#{dst_label}"
|
309
|
+
@zones_names ||= { "STANDARD" => ::ActiveSupport::TimeZone.all.collect(&:to_s) }
|
310
|
+
|
311
|
+
if with_dst && @zones_names[dst_key].blank? then
|
312
|
+
@zones_names[dst_key] = []
|
313
|
+
|
314
|
+
::ActiveSupport::TimeZone.all.each do |zone|
|
315
|
+
zone.aliases.each do |zone_alias|
|
316
|
+
@zones_names[dst_key] << zone.to_str(zone_alias)
|
317
|
+
@zones_names[dst_key] << zone.to_str_with_dst(dst_label, nil, zone_alias) if zone.uses_dst? && zone_alias !~ /(#{Regexp.quote(dst_label)})$/
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
@zones_names[dst_key]= @zones_names[dst_key].uniq.compact.sort { |a,b| ::ActiveSupport::TimeZone.compare(a, b) } # Sort by name
|
322
|
+
end
|
323
|
+
|
324
|
+
@zones_names[with_dst ? dst_key : "STANDARD"]
|
325
|
+
end
|
326
|
+
|
327
|
+
# Returns a string representation of a timezone.
|
328
|
+
#
|
329
|
+
# ```ruby
|
330
|
+
# DateTime.parameterize_zone(ActiveSupport::TimeZone["Pacific Time (US & Canada)"])
|
331
|
+
# # => "-0800@pacific-time-us-canada"
|
332
|
+
# ```
|
333
|
+
# @param tz [TimeZone] The zone to represent.
|
334
|
+
# @param with_offset [Boolean] If to include offset into the representation.
|
335
|
+
# @return [String] A string representation which can be used for searches.
|
336
|
+
def parameterize_zone(tz, with_offset = true)
|
337
|
+
tz = tz.to_s if !tz.is_a?(::String)
|
338
|
+
|
339
|
+
if tz =~ /^(\([a-z]+([+-])(\d{2})(:?)(\d{2})\)\s(.+))$/i then
|
340
|
+
with_offset ? "#{$2}#{$3}#{$5}@#{$6.parameterize}" : $6.parameterize
|
341
|
+
elsif !with_offset then
|
342
|
+
tz.gsub(/^([+-]?(\d{2})(:?)(\d{2})@)/, "")
|
343
|
+
else
|
344
|
+
tz.parameterize
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
# Finds a parameterized timezone.
|
349
|
+
# @see DateTime#parameterize_zone
|
350
|
+
#
|
351
|
+
# @param tz [String] The zone to unparameterize.
|
352
|
+
# @param as_string [Boolean] If return just the zone name.
|
353
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
|
354
|
+
# @return [String|TimeZone] The found timezone or `nil` if the zone is not valid.
|
355
|
+
def unparameterize_zone(tz, as_string = false, dst_label = nil)
|
356
|
+
tz = self.parameterize_zone(tz, false)
|
357
|
+
rv = catch(:zone) do
|
358
|
+
self.list_all(true, dst_label).each do |zone|
|
359
|
+
throw(:zone, zone) if self.parameterize_zone(zone, false) =~ /(#{Regexp.quote(tz)})$/
|
360
|
+
end
|
361
|
+
|
362
|
+
nil
|
363
|
+
end
|
364
|
+
|
365
|
+
if rv then
|
366
|
+
(as_string ? rv : self.find(rv, dst_label))
|
367
|
+
else
|
368
|
+
nil
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
# Compares two timezones. They are sorted by the location name.
|
373
|
+
#
|
374
|
+
# @param left [String|TimeZone] The first zone name to compare.
|
375
|
+
# @param right [String|TimeZone] The second zone name to compare.
|
376
|
+
# @return [Fixnum] The result of comparison, like Ruby's operator `<=>`.
|
377
|
+
def compare(left, right)
|
378
|
+
left = left.to_str if left.is_a?(::ActiveSupport::TimeZone)
|
379
|
+
right = right.to_str if right.is_a?(::ActiveSupport::TimeZone)
|
380
|
+
left.ensure_string.split(" ", 2)[1] <=> right.ensure_string.split(" ", 2)[1]
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
# Returns a list of valid aliases (city names) for this timezone (basing on offset).
|
385
|
+
#
|
386
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
|
387
|
+
# @return [Array] A list of aliases for this timezone
|
388
|
+
def aliases(dst_label = nil)
|
389
|
+
reference = self.name
|
390
|
+
reference = self.class::MAPPING[self.name] if self.class::MAPPING.has_key?(self.name) # We are an alias
|
391
|
+
reference = reference.gsub("_", " ")
|
392
|
+
|
393
|
+
if @aliases.blank? then
|
394
|
+
# First we search for aliases by name
|
395
|
+
@aliases = [reference]
|
396
|
+
|
397
|
+
self.class::MAPPING.each do |name, zone|
|
398
|
+
if zone.gsub("_", " ") == reference then
|
399
|
+
if name == "International Date Line West" || name == "UTC" || name.include?("(US & Canada)")
|
400
|
+
@aliases << name
|
401
|
+
else
|
402
|
+
@aliases << reference.gsub(/\/.*/, "/" + name)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
@aliases = @aliases.uniq.compact.sort
|
408
|
+
end
|
409
|
+
|
410
|
+
@aliases
|
411
|
+
end
|
412
|
+
|
413
|
+
# Returns the current offset for this timezone, taking care of Daylight Saving Time (DST).
|
414
|
+
#
|
415
|
+
# @param rational [Boolean] If to return the offset as a Rational.
|
416
|
+
# @param date [DateTime] The date to consider. Defaults to now.
|
417
|
+
# @return [Fixnum|Rational] The offset of this timezone.
|
418
|
+
def current_offset(rational = false, date = nil)
|
419
|
+
date ||= ::DateTime.now
|
420
|
+
|
421
|
+
dst_period = self.dst_period
|
422
|
+
|
423
|
+
rv = (self.period_for_utc(date.utc).dst? ? self.dst_offset : self.offset)
|
424
|
+
rational ? self.class.rationalize_offset(rv) : rv
|
425
|
+
end
|
426
|
+
|
427
|
+
# Returns the standard offset for this timezone.
|
428
|
+
#
|
429
|
+
# @param rational [Boolean] If to return the offset as a Rational.
|
430
|
+
# @return [Fixnum|Rational] The offset of this timezone.
|
431
|
+
def offset(rational = false)
|
432
|
+
rv = self.utc_offset
|
433
|
+
rational ? self.class.rationalize_offset(rv) : rv
|
434
|
+
end
|
435
|
+
|
436
|
+
# Gets a period for this timezone when the Daylight Saving Time (DST) is active (it takes care of different hemispheres).
|
437
|
+
#
|
438
|
+
# @param year [Fixnum] The year to which refer to. Defaults to the current year.
|
439
|
+
# @return [TimezonePeriod] A period when the Daylight Saving Time (DST) is active or `nil` if the timezone doesn't use DST for that year.
|
440
|
+
def dst_period(year = nil)
|
441
|
+
year ||= ::Date.today.year
|
442
|
+
|
443
|
+
nothern_summer = ::DateTime.civil(year, 7, 15).utc # This is a representation of a summer period in the Northern Hemisphere.
|
444
|
+
southern_summer = ::DateTime.civil(year, 1, 15).utc # This is a representation of a summer period in the Northern Hemisphere.
|
445
|
+
|
446
|
+
period = self.period_for_utc(nothern_summer)
|
447
|
+
period = self.period_for_utc(southern_summer) if !period.dst?
|
448
|
+
period.dst? ? period : nil
|
449
|
+
end
|
450
|
+
|
451
|
+
# Checks if the timezone uses Daylight Saving Time (DST) for that date or year.
|
452
|
+
#
|
453
|
+
# @param reference [Object] The date or year to check. Defaults to the current year.
|
454
|
+
# @return [Boolean] `true` if the zone uses DST for that date or year, `false` otherwise.
|
455
|
+
def uses_dst?(reference = nil)
|
456
|
+
if reference.respond_to?(:year) && reference.respond_to?(:utc) then # This is a date like object
|
457
|
+
self.dst_period(reference.year).present? && self.period_for_utc(reference.utc).dst?
|
458
|
+
else
|
459
|
+
self.dst_period(reference).present?
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
# Return the correction applied to the standard offset the timezone when the Daylight Saving Time (DST) is active.
|
464
|
+
#
|
465
|
+
# @param rational [Boolean] If to return the offset as a Rational.
|
466
|
+
# @param year [Fixnum] The year to which refer to. Defaults to the current year.
|
467
|
+
# @return [Fixnum|Rational] The correction for dst.
|
468
|
+
def dst_correction(rational = false, year = nil)
|
469
|
+
period = self.dst_period(year)
|
470
|
+
rv = period ? period.std_offset : 0
|
471
|
+
rational ? self.class.rationalize_offset(rv) : rv
|
472
|
+
end
|
473
|
+
|
474
|
+
# Returns the standard offset for this timezone timezone when the Daylight Saving Time (DST) is active.
|
475
|
+
#
|
476
|
+
# @param rational [Boolean] If to return the offset as a Rational.
|
477
|
+
# @param year [Fixnum] The year to which refer to. Defaults to the current year.
|
478
|
+
# @return [Fixnum|Rational] The DST offset for this timezone or `0`, if the timezone doesn't use DST for that year.
|
479
|
+
def dst_offset(rational = false, year = nil)
|
480
|
+
period = self.dst_period(year)
|
481
|
+
rv = period ? period.utc_total_offset : 0
|
482
|
+
rational ? self.class.rationalize_offset(rv) : rv
|
483
|
+
end
|
484
|
+
|
485
|
+
# Returns the name for this zone with Daylight Saving Time (DST) active.
|
486
|
+
#
|
487
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
|
488
|
+
# @param year [Fixnum] The year to which refer to. Defaults to the current year.
|
489
|
+
# @param name [String] The name to use for this zone. Defaults to the zone name.
|
490
|
+
# @return [String] The name for the zone with DST or `nil`, if the timezone doesn't use DST for that year.
|
491
|
+
def dst_name(dst_label = nil, year = nil, name = nil)
|
492
|
+
dst_label ||= "(DST)"
|
493
|
+
name ||= self.name
|
494
|
+
|
495
|
+
self.uses_dst?(year) ? "#{name} #{dst_label}" : nil
|
496
|
+
end
|
497
|
+
|
498
|
+
# Returns the name for this zone with Daylight Saving Time (DST) active.
|
499
|
+
#
|
500
|
+
# @param name [String] The name to use for this zone. Defaults to the zone name.
|
501
|
+
# @param colon [Boolean] If to put the colon in the output string.
|
502
|
+
# @return [String] The name for this zone.
|
503
|
+
def to_str(name = nil, colon = true)
|
504
|
+
name ||= self.aliases.first
|
505
|
+
"(GMT#{self.formatted_offset(colon)}) #{name}"
|
506
|
+
end
|
507
|
+
|
508
|
+
# Returns a string representation for this zone with Daylight Saving Time (DST) active.
|
509
|
+
#
|
510
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
|
511
|
+
# @param year [Fixnum] The year to which refer to. Defaults to the current year.
|
512
|
+
# @param name [String] The name to use for this zone. Defaults to the zone name.
|
513
|
+
# @return [String] The string representation for the zone with DST or `nil`, if the timezone doesn't use DST for that year.
|
514
|
+
def to_str_with_dst(dst_label = nil, year = nil, name = nil)
|
515
|
+
dst_label ||= "(DST)"
|
516
|
+
name ||= self.aliases.first
|
517
|
+
|
518
|
+
if self.uses_dst?(year) then
|
519
|
+
period = self.dst_period(year)
|
520
|
+
offset = self.class.seconds_to_utc_offset(period.utc_total_offset)
|
521
|
+
"(GMT#{offset}) #{name} #{dst_label}"
|
522
|
+
else
|
523
|
+
nil
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
# Returns a parametized string representation for this zone.
|
528
|
+
#
|
529
|
+
# @param with_offset [Boolean] If to include offset into the representation.
|
530
|
+
# @param name [String] The name to use for this zone. Defaults to the zone name.
|
531
|
+
# @return [String] The parametized string representation for this zone.
|
532
|
+
def to_str_parameterized(with_offset = true, name = nil)
|
533
|
+
::ActiveSupport::TimeZone.parameterize_zone(name || self.to_str, with_offset)
|
534
|
+
end
|
535
|
+
|
536
|
+
# Returns a parametized string representation for this zone with Daylight Saving Time (DST) active.
|
537
|
+
#
|
538
|
+
# @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
|
539
|
+
# @param with_offset [Boolean] If to include offset into the representation.
|
540
|
+
# @param year [Fixnum] The year to which refer to. Defaults to the current year.
|
541
|
+
# @param name [String] The name to use for this zone. Defaults to the zone name.
|
542
|
+
# @return [String] The parametized string representation for this zone with DST or `nil`, if the timezone doesn't use DST for that year.
|
543
|
+
def to_str_with_dst_parameterized(dst_label = nil, with_offset = true, year = nil, name = nil)
|
544
|
+
rv = self.to_str_with_dst(dst_label, year, name)
|
545
|
+
rv ? ::ActiveSupport::TimeZone.parameterize_zone(rv) : nil
|
546
|
+
end
|
547
|
+
end
|
548
|
+
end
|