active_date_range 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_date_range/i18n"
4
+
5
+ module ActiveDateRange
6
+ # Translates a <tt>DateRange</tt> to a human readable format. Localization and translations are
7
+ # handled by I18n.
8
+ #
9
+ # Valid <tt>format</tt> parameters:
10
+ # - <tt>short</tt> (default): Jan 1, 2021 - Jan 15, 2021
11
+ # - <tt>long</tt>: January 12, 2021 - January 15, 2021
12
+ # - <tt>relative</tt>: when available, returns a relative translation like "this month" or "next year".
13
+ # - <tt>explicit</tt>: never shortens a <tt>short</tt> or <tt>long</tt> format (see below)
14
+ #
15
+ # Unless you use the <tt>:explicit</tt> format, the translation is as short as possible:
16
+ #
17
+ # DateRange.parse("20210101..20210101").humanize # => "Jan 1, 2021"
18
+ # DateRange.parse("20210101..20210115").humanize # => "Jan 1 - Jan 15, 2021"
19
+ # DateRange.parse("20210101..20220115").humanize # => "Jan 1 2021 - Jan 15, 2022"
20
+ # DateRange.parse("202101..202101").humanize # => "Jan 2021"
21
+ # DateRange.parse("202101..202102").humanize # => "Jan - Feb 2021"
22
+ # DateRange.parse("202101..202202").humanize # => "Jan 2021 - Feb 2022"
23
+ # DateRange.parse("202101..202103").humanize # => "Q1 2021"
24
+ # DateRange.parse("202101..202106").humanize # => "Q1 - Q2 2021"
25
+ # DateRange.parse("202101..202206").humanize # => "Q1 2021 - Q2 2022"
26
+ # DateRange.parse("202101..202112").humanize # => "2021"
27
+ # DateRange.parse("202101..202212").humanize # => "2021 - 2021"
28
+ #
29
+ # Translations and formats are completely customizable through <tt>I18n</tt>, see
30
+ # <tt>locales/en.yml</tt> for an overview of translatable keys.
31
+ class Humanizer
32
+ attr_reader :date_range, :format
33
+
34
+ FORMATS = %i[short long relative explicit]
35
+
36
+ def initialize(date_range, format: :short)
37
+ @date_range = date_range
38
+ raise ArgumentError, "Unknown format #{format} for humanize, valid formats: #{FORMATS.join(", ")}" unless FORMATS.include?(format)
39
+
40
+ @format = format
41
+ end
42
+
43
+ def humanize
44
+ return day_range if format == :explicit
45
+
46
+ if format == :relative
47
+ return relative if date_range.relative_param
48
+
49
+ @format = :short
50
+ end
51
+
52
+ one_day || year || quarter || month || day_range
53
+ end
54
+
55
+ private
56
+ def relative
57
+ I18n.translate(date_range.relative_param, scope: %i[date relative_range])
58
+ end
59
+
60
+ def one_day
61
+ return unless date_range.days == 1
62
+
63
+ I18n.localize(date_range.begin, format: :"#{format}_day")
64
+ end
65
+
66
+ def year
67
+ return unless date_range.full_year? || format == :explicit
68
+
69
+ if date_range.one_year?
70
+ date_range.begin.year.to_s
71
+ else
72
+ range(date_range.begin.year, date_range.end.year)
73
+ end
74
+ end
75
+
76
+ def quarter
77
+ return unless date_range.full_quarter? || format == :explicit
78
+
79
+ if date_range.one_quarter?
80
+ I18n.translate(
81
+ "#{format}_quarter",
82
+ scope: :date, quarter: "#{date_range.begin.quarter} #{date_range.begin.year}"
83
+ )
84
+ else
85
+ begin_quarter = if date_range.same_year?
86
+ date_range.begin.quarter
87
+ else
88
+ "#{date_range.begin.quarter} #{date_range.begin.year}"
89
+ end
90
+
91
+ range(
92
+ I18n.translate("#{format}_quarter", scope: :date, quarter: begin_quarter),
93
+ I18n.translate(
94
+ "#{format}_quarter",
95
+ scope: :date, quarter: "#{date_range.end.quarter} #{date_range.end.year}"
96
+ )
97
+ )
98
+ end
99
+ end
100
+
101
+ def month
102
+ return unless date_range.one_month?
103
+
104
+ I18n.localize(date_range.begin, format: :"#{format}_month")
105
+ end
106
+
107
+ def day_range
108
+ month_format = date_range.full_month? ? "month" : "day_month"
109
+ abbr = "abbr_" if date_range.same_year?
110
+
111
+ range(
112
+ I18n.localize(date_range.begin, format: :"#{abbr}#{format}_#{month_format}"),
113
+ I18n.localize(date_range.end, format: :"#{format}_#{month_format}")
114
+ )
115
+ end
116
+
117
+ def range(range_begin, range_end)
118
+ I18n.translate(:range, scope: :date, begin: range_begin, end: range_end)
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,9 @@
1
+ begin
2
+ require "i18n"
3
+ require "i18n/backend/fallbacks"
4
+ rescue LoadError => e
5
+ $stderr.puts "The i18n gem is not available. Please add it to your Gemfile and run bundle install"
6
+ raise e
7
+ end
8
+
9
+ I18n.load_path << File.expand_path("locale/en.yml", __dir__)
@@ -0,0 +1,38 @@
1
+ en:
2
+ date:
3
+ formats:
4
+ abbr_explicit_day_month: "%b %d"
5
+ abbr_explicit_month: "%B"
6
+ abbr_long_day_month: "%B %d"
7
+ abbr_long_month: "%B"
8
+ abbr_short_day_month: "%b %d"
9
+ abbr_short_month: "%b"
10
+ default: "%Y-%m-%d"
11
+ explicit_day: "%b %d, %Y"
12
+ explicit_day_month: "%b %d, %Y"
13
+ explicit_month: "%B %Y"
14
+ explicit_year: "%B %Y"
15
+ long: "%B %d, %Y"
16
+ long_day: "%B %d, %Y"
17
+ long_day_month: "%B %d, %Y"
18
+ long_month: "%B %Y"
19
+ month: "%B"
20
+ short: "%b %d"
21
+ short_day: "%b %d, %Y"
22
+ short_day_month: "%b %d, %Y"
23
+ short_month: "%b %Y"
24
+ short_year: "%y"
25
+ relative_range:
26
+ next_month: "next month"
27
+ next_quarter: "next quarter"
28
+ next_year: "next year"
29
+ prev_month: "the previous month"
30
+ prev_quarter: "the previous quarter"
31
+ prev_year: "the previous year"
32
+ this_month: "this month"
33
+ this_quarter: "this quarter"
34
+ this_year: "this year"
35
+ today: "today"
36
+ long_quarter: "quarter %{quarter}"
37
+ short_quarter: "Q%{quarter}"
38
+ range: "%{begin} - %{end}"
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveDateRange
4
+ VERSION = "0.1.0"
5
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_date_range
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Edwin Vlieg
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-04-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: i18n
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-packaging
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-performance
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: ActiveDateRange provides a range of dates with a powerful API to manipulate
98
+ and use date ranges in your software.
99
+ email:
100
+ - edwin@moneybird.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".rubocop.yml"
107
+ - ".travis.yml"
108
+ - CHANGELOG.md
109
+ - Gemfile
110
+ - Gemfile.lock
111
+ - Guardfile
112
+ - LICENSE
113
+ - README.md
114
+ - Rakefile
115
+ - active_date_range.gemspec
116
+ - bin/console
117
+ - bin/setup
118
+ - lib/active_date_range.rb
119
+ - lib/active_date_range/core_ext/date.rb
120
+ - lib/active_date_range/core_ext/integer.rb
121
+ - lib/active_date_range/date_range.rb
122
+ - lib/active_date_range/humanizer.rb
123
+ - lib/active_date_range/i18n.rb
124
+ - lib/active_date_range/locale/en.yml
125
+ - lib/active_date_range/version.rb
126
+ homepage: https://github.com/moneybird/active-date-range
127
+ licenses: []
128
+ metadata:
129
+ homepage_uri: https://github.com/moneybird/active-date-range
130
+ source_code_uri: https://github.com/moneybird/active-date-range
131
+ changelog_uri: https://github.com/moneybird/active-date-range/CHANGELOG.md
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: 2.3.0
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubygems_version: 3.2.16
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: DateRange for ActiveSupport
151
+ test_files: []