dotiw 4.0.1 → 5.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.
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file was generated by Appraisal
2
4
 
3
- source "http://rubygems.org"
5
+ source 'http://rubygems.org'
4
6
 
5
- gem "rails", "~> 4.0"
7
+ gem 'rails', '~> 4.0'
6
8
 
7
- gemspec path: "../"
9
+ gemspec path: '../'
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file was generated by Appraisal
2
4
 
3
- source "http://rubygems.org"
5
+ source 'http://rubygems.org'
4
6
 
5
- gem "rails", "~> 5.0.0"
7
+ gem 'rails', '~> 5.0.0'
6
8
 
7
- gemspec path: "../"
9
+ gemspec path: '../'
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file was generated by Appraisal
2
4
 
3
- source "http://rubygems.org"
5
+ source 'http://rubygems.org'
4
6
 
5
- gem "rails", "~> 5.1"
7
+ gem 'rails', '~> 5.1.0'
6
8
 
7
- gemspec path: "../"
9
+ gemspec path: '../'
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file was generated by Appraisal
4
+
5
+ source 'http://rubygems.org'
6
+
7
+ gem 'rails', '~> 5.2.0'
8
+
9
+ gemspec path: '../'
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file was generated by Appraisal
4
+
5
+ source 'http://rubygems.org'
6
+
7
+ gem 'rails', '~> 6.0.0'
8
+
9
+ gemspec path: '../'
@@ -1,30 +1,41 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'i18n'
4
4
 
5
- # Rails hacks
6
- if defined?(ActionView::Helpers)
7
- require 'dotiw/action_view_ext/helpers/date_helper'
8
- end
5
+ require 'active_support'
6
+ require 'active_support/core_ext'
9
7
 
10
8
  module DOTIW
9
+ extend ActiveSupport::Autoload
10
+
11
+ eager_autoload do
12
+ autoload :VERSION, 'dotiw/version'
13
+ autoload :TimeHash, 'dotiw/time_hash'
14
+ autoload :Methods, 'dotiw/methods'
15
+ end
16
+
11
17
  extend self
12
-
13
- autoload :VERSION, 'dotiw/version'
14
- autoload :TimeHash, 'dotiw/time_hash'
15
18
 
16
19
  DEFAULT_I18N_SCOPE = :'datetime.dotiw'
17
20
 
18
- def init_i18n
21
+ def init_i18n!
19
22
  I18n.load_path.unshift(*locale_files)
20
23
  I18n.reload!
21
24
  end
22
25
 
23
- protected
26
+ protected
27
+
24
28
  # Returns all locale files shipped with library
25
29
  def locale_files
26
30
  Dir[File.join(File.dirname(__FILE__), 'dotiw', 'locale', '**/*')]
27
31
  end
28
32
  end # DOTIW
29
33
 
30
- DOTIW.init_i18n
34
+ DOTIW.init_i18n!
35
+
36
+ begin
37
+ require 'action_view'
38
+ require_relative 'dotiw/action_view/helpers/date_helper'
39
+ rescue LoadError
40
+ # TODO: don't rely on exception
41
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ module Helpers
5
+ module DateHelper
6
+ alias_method :_distance_of_time_in_words, :distance_of_time_in_words
7
+ alias_method :_time_ago_in_words, :time_ago_in_words
8
+
9
+ include DOTIW::Methods
10
+
11
+ def distance_of_time_in_words(from_time, to_time = 0, include_seconds_or_options = {}, options = {})
12
+ return _distance_of_time_in_words(from_time, to_time, options) if options.delete(:vague)
13
+ super
14
+ end
15
+
16
+ def distance_of_time_in_percent(from_time, current_time, to_time, options = {})
17
+ options[:precision] ||= 0
18
+ distance = to_time - from_time
19
+ result = ((current_time - from_time) / distance) * 100
20
+ number_with_precision(result, options).to_s + '%'
21
+ end
22
+ end # DateHelper
23
+ end # Helpers
24
+ end # ActionView
@@ -2,45 +2,52 @@ ar:
2
2
  datetime:
3
3
  dotiw:
4
4
  seconds:
5
- one: ثانية
5
+ zero: ثانية
6
+ one: ثانية واحدة
6
7
  two: ثانيتين
7
- few: "%{count} ثواني"
8
- many: "%{count} ثواني"
9
- other: "%{count} ثواني"
8
+ few: "%{count} توانٍ"
9
+ many: "%{count} ثانية"
10
+ other: "%{count} ثانية"
10
11
  minutes:
11
- one: دقيقة
12
+ zero: دقيقة
13
+ one: دقيقة واحدة
12
14
  two: دقيقتين
13
15
  few: "%{count} دقائق"
14
- many: "%{count} دقائق"
15
- other: "%{count} دقائق"
16
+ many: "%{count} دقيقة"
17
+ other: "%{count} دقيقة"
16
18
  hours:
17
- one: ساعة
19
+ zero: ساعة
20
+ one: ساعة واحدة
18
21
  two: ساعتين
19
22
  few: "%{count} ساعات"
20
- many: "%{count} ساعات"
21
- other: "%{count} ساعات"
23
+ many: "%{count} ساعة"
24
+ other: "%{count} ساعة"
22
25
  days:
23
- one: يوم
24
- two: يومان
25
- few: "%{count} أيام"
26
- many: "%{count} أيام"
27
- other: "%{count} أيام"
26
+ zero: يوم
27
+ one: يوم واحد
28
+ two: يومين
29
+ few: "%{count} أيام"
30
+ many: "%{count} يومًا"
31
+ other: "%{count} يوم"
28
32
  weeks:
29
- one: أسبوع
30
- two: إسبوعين
33
+ zero: أسبوع
34
+ one: أسبوع واحدة
35
+ two: أسبوعين
31
36
  few: "%{count} أسابيع"
32
37
  many: "%{count} أسابيع"
33
- other: "%{count} أسابيع"
38
+ other: "%{count} أسيوع"
34
39
  months:
35
- one: شهر
40
+ zero: شهر
41
+ one: شهر واحد
36
42
  two: شهرين
37
43
  few: "%{count} أشهر"
38
- many: "%{count} أشهر"
39
- other: "%{count} أشهر"
44
+ many: "%{count} شهراً"
45
+ other: "%{count} شهر"
40
46
  years:
41
- one: سنة
42
- two: سنتان
43
- few: "%{count} سنوات"
44
- many: "%{count} سنوات"
45
- other: "%{count} سنوات"
46
- less_than_x: أقل من %{distance}
47
+ zero: عام
48
+ one: عام واحد
49
+ two: عامين
50
+ few: "%{count} أعوام"
51
+ many: "%{count} عاماً"
52
+ other: "%{count} عام"
53
+ less_than_x: "%{distance} أقل من"
@@ -4,29 +4,36 @@ pl:
4
4
  seconds:
5
5
  one: "1 sekunda"
6
6
  few: "%{count} sekundy"
7
+ many: "%{count} sekund"
7
8
  other: "%{count} sekund"
8
9
  minutes:
9
10
  one: "1 minuta"
10
11
  few: "%{count} minuty"
12
+ many: "%{count} minut"
11
13
  other: "%{count} minut"
12
14
  hours:
13
15
  one: "1 godzina"
14
16
  few: "%{count} godziny"
17
+ many: "%{count} godzin"
15
18
  other: "%{count} godzin"
16
19
  days:
17
20
  one: "1 dzień"
18
21
  few: "%{count} dni"
22
+ many: "%{count} dni"
19
23
  other: "%{count} dni"
20
24
  weeks:
21
25
  one: "1 tydzień"
22
26
  few: "%{count} tygodnie"
27
+ many: "%{count} tygodni"
23
28
  other: "%{count} tygodni"
24
29
  months:
25
30
  one: "1 miesiąc"
26
31
  few: "%{count} miesiące"
32
+ many: "%{count} miesięcy"
27
33
  other: "%{count} miesięcy"
28
34
  years:
29
35
  one: "1 rok"
30
36
  few: "%{count} lata"
37
+ many: "%{count} lat"
31
38
  other: "%{count} lat"
32
39
  less_than_x: "mniej niż %{distance}"
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DOTIW
4
+ module Methods
5
+ def distance_of_time_in_words_hash(from_time, to_time, options = {})
6
+ from_time = from_time.to_time if !from_time.is_a?(Time) && from_time.respond_to?(:to_time)
7
+ to_time = to_time.to_time if !to_time.is_a?(Time) && to_time.respond_to?(:to_time)
8
+
9
+ DOTIW::TimeHash.new(nil, from_time, to_time, options).to_hash
10
+ end
11
+
12
+ def distance_of_time(seconds, options = {})
13
+ options[:include_seconds] ||= true
14
+ _display_time_in_words DOTIW::TimeHash.new(seconds, nil, nil, options).to_hash, options
15
+ end
16
+
17
+ def distance_of_time_in_words(from_time, to_time = 0, include_seconds_or_options = {}, options = {})
18
+ if include_seconds_or_options.is_a?(Hash)
19
+ options = include_seconds_or_options
20
+ else
21
+ options[:include_seconds] ||= !!include_seconds_or_options
22
+ end
23
+ return distance_of_time(from_time, options) if to_time == 0
24
+
25
+ hash = distance_of_time_in_words_hash(from_time, to_time, options)
26
+ _display_time_in_words(hash, options)
27
+ end
28
+
29
+ def time_ago_in_words(from_time, include_seconds_or_options = {})
30
+ distance_of_time_in_words(from_time, Time.current, include_seconds_or_options)
31
+ end
32
+
33
+ private
34
+
35
+ def _display_time_in_words(hash, options = {})
36
+ options.reverse_merge!(
37
+ include_seconds: false
38
+ ).symbolize_keys!
39
+
40
+ include_seconds = options.delete(:include_seconds)
41
+ hash.delete(:seconds) if !include_seconds && hash[:minutes]
42
+
43
+ options[:except] = Array.wrap(options[:except]).map!(&:to_sym) if options[:except]
44
+ options[:only] = Array.wrap(options[:only]).map!(&:to_sym) if options[:only]
45
+
46
+ # Remove all the values that are nil or excluded. Keep the required ones.
47
+ hash.delete_if do |key, value|
48
+ value.nil? || value.zero? ||
49
+ options[:except]&.include?(key) ||
50
+ (options[:only] && !options[:only].include?(key))
51
+ end
52
+
53
+ i18n_scope = options.delete(:scope) || DOTIW::DEFAULT_I18N_SCOPE
54
+ if hash.empty?
55
+ fractions = DOTIW::TimeHash::TIME_FRACTIONS
56
+ fractions &= options[:only] if options[:only]
57
+ fractions -= options[:except] if options[:except]
58
+
59
+ I18n.with_options locale: options[:locale], scope: i18n_scope do |locale|
60
+ # e.g. try to format 'less than 1 days', fallback to '0 days'
61
+ return locale.translate :less_than_x,
62
+ distance: locale.translate(fractions.first, count: 1),
63
+ default: locale.translate(fractions.first, count: 0)
64
+ end
65
+ end
66
+
67
+ output = []
68
+ I18n.with_options locale: options[:locale], scope: i18n_scope do |locale|
69
+ output = hash.map { |key, value| locale.t(key, count: value) }
70
+ end
71
+
72
+ options.delete(:except)
73
+ options.delete(:only)
74
+ highest_measures = options.delete(:highest_measures)
75
+ highest_measures = 1 if options.delete(:highest_measure_only)
76
+ output = output[0...highest_measures] if highest_measures
77
+
78
+ options[:words_connector] ||= I18n.translate :'datetime.dotiw.words_connector',
79
+ default: :'support.array.words_connector',
80
+ locale: options[:locale]
81
+ options[:two_words_connector] ||= I18n.translate :'datetime.dotiw.two_words_connector',
82
+ default: :'support.array.two_words_connector',
83
+ locale: options[:locale]
84
+ options[:last_word_connector] ||= I18n.translate :'datetime.dotiw.last_word_connector',
85
+ default: :'support.array.last_word_connector',
86
+ locale: options[:locale]
87
+
88
+ output.to_sentence(options)
89
+ end
90
+ end
91
+ end # DOTIW
@@ -1,25 +1,25 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module DOTIW
4
4
  class TimeHash
5
- TIME_FRACTIONS = [:seconds, :minutes, :hours, :days, :weeks, :months, :years]
6
-
7
- attr_accessor :distance, :smallest, :largest, :from_time, :to_time
8
-
9
- def initialize(distance, from_time = nil, to_time = nil, options = {})
10
- self.output = ActiveSupport::OrderedHash.new
11
- self.options = options
12
- self.distance = distance
13
- self.from_time = from_time || Time.current
14
- self.to_time = to_time || (@to_time_not_given = true && self.from_time + self.distance.seconds)
15
- self.smallest, self.largest = [self.from_time, self.to_time].minmax
16
- self.to_time += 1.hour if @to_time_not_given && self.smallest.dst? && !self.largest.dst?
17
- self.to_time -= 1.hour if @to_time_not_given && !self.smallest.dst? && self.largest.dst?
18
- self.smallest, self.largest = [self.from_time, self.to_time].minmax
19
- self.distance ||= begin
5
+ TIME_FRACTIONS = %i[seconds minutes hours days weeks months years].freeze
6
+
7
+ attr_reader :distance, :smallest, :largest, :from_time, :to_time
8
+
9
+ def initialize(distance, from_time, to_time = nil, options = {})
10
+ @output = {}
11
+ @options = options
12
+ @distance = distance
13
+ @from_time = from_time || Time.current
14
+ @to_time = to_time || (@to_time_not_given = true && @from_time + distance.seconds)
15
+ @smallest, @largest = [@from_time, @to_time].minmax
16
+ @to_time += 1.hour if @to_time_not_given && smallest.dst? && !largest.dst?
17
+ @to_time -= 1.hour if @to_time_not_given && !smallest.dst? && largest.dst?
18
+ @smallest, @largest = [@from_time, @to_time].minmax
19
+ @distance ||= begin
20
20
  d = largest - smallest
21
- d -= 1.hour if self.smallest.dst? && !self.largest.dst?
22
- d += 1.hour if !self.smallest.dst? && self.largest.dst?
21
+ d -= 1.hour if smallest.dst? && !largest.dst?
22
+ d += 1.hour if !smallest.dst? && largest.dst?
23
23
  d
24
24
  end
25
25
 
@@ -30,16 +30,16 @@ module DOTIW
30
30
  output
31
31
  end
32
32
 
33
- private
34
- attr_accessor :options, :output
33
+ private
34
+
35
+ attr_reader :options, :output
35
36
 
36
37
  def build_time_hash
37
38
  if accumulate_on = options.delete(:accumulate_on)
38
39
  accumulate_on = accumulate_on.to_sym
39
- if accumulate_on == :years
40
- return build_time_hash
41
- end
42
- TIME_FRACTIONS.index(accumulate_on).downto(0) { |i| self.send("build_#{TIME_FRACTIONS[i]}") }
40
+ return build_time_hash if accumulate_on == :years
41
+
42
+ TIME_FRACTIONS.index(accumulate_on).downto(0) { |i| send("build_#{TIME_FRACTIONS[i]}") }
43
43
  else
44
44
  while distance > 0
45
45
  if distance < 1.minute
@@ -63,23 +63,23 @@ module DOTIW
63
63
 
64
64
  def build_seconds
65
65
  output[:seconds] = distance.to_i
66
- self.distance = 0
66
+ @distance = 0
67
67
  end
68
68
 
69
69
  def build_minutes
70
- output[:minutes], self.distance = distance.divmod(1.minute.to_i)
70
+ output[:minutes], @distance = distance.divmod(1.minute.to_i)
71
71
  end
72
72
 
73
73
  def build_hours
74
- output[:hours], self.distance = distance.divmod(1.hour.to_i)
74
+ output[:hours], @distance = distance.divmod(1.hour.to_i)
75
75
  end
76
76
 
77
77
  def build_days
78
- output[:days], self.distance = distance.divmod(1.day.to_i) if output[:days].nil?
78
+ output[:days], @distance = distance.divmod(1.day.to_i) unless output[:days]
79
79
  end
80
80
 
81
81
  def build_weeks
82
- output[:weeks], self.distance = distance.divmod(1.week.to_i) if output[:weeks].nil?
82
+ output[:weeks], @distance = distance.divmod(1.week.to_i) unless output[:weeks]
83
83
  end
84
84
 
85
85
  def build_months
@@ -110,7 +110,7 @@ module DOTIW
110
110
  if weeks < 0
111
111
  # Convert the last month to a week and add to total
112
112
  months -= 1
113
- last_month = largest.advance(:months => -1)
113
+ last_month = largest.advance(months: -1)
114
114
  days_in_month = Time.days_in_month(last_month.month, last_month.year)
115
115
  weeks += days_in_month / 7
116
116
  days += days_in_month % 7
@@ -118,6 +118,12 @@ module DOTIW
118
118
  days -= 7
119
119
  weeks += 1
120
120
  end
121
+
122
+ if weeks == -1
123
+ months -= 1
124
+ weeks = 4
125
+ days -= 4
126
+ end
121
127
  end
122
128
 
123
129
  if months < 0
@@ -131,9 +137,9 @@ module DOTIW
131
137
  output[:weeks] = weeks
132
138
  output[:days] = days
133
139
 
134
- total_days, self.distance = distance.abs.divmod(1.day.to_i)
140
+ total_days, @distance = distance.abs.divmod(1.day.to_i)
135
141
 
136
- [total_days, self.distance]
142
+ [total_days, @distance]
137
143
  end
138
144
  end # TimeHash
139
145
  end # DOTIW