From ce8123bf0710f4cc8b10ed5f54579a17b2aa6c70 Mon Sep 17 00:00:00 2001 From: Arnaud Meuret Date: Tue, 20 May 2025 14:42:54 +0900 Subject: [PATCH 1/2] Fast forward 12 years of Ruby evolution --- Gemfile | 17 +++-- Gemfile.lock | 141 +++++++++++++++++++++++++++++++++-------- Rakefile | 12 ++-- lib/time_diff.rb | 26 ++++++-- test/test_time_diff.rb | 13 ++-- 5 files changed, 154 insertions(+), 55 deletions(-) diff --git a/Gemfile b/Gemfile index 4f87652..fed4fc1 100644 --- a/Gemfile +++ b/Gemfile @@ -1,16 +1,15 @@ -source "http://rubygems.org" +source 'http://rubygems.org' -gem 'activesupport' +# gem 'coveralls_reborn', require: false gem 'i18n' -gem 'coveralls', :require => false -# Add dependencies required to use your gem here. -# Example: -# gem "activesupport", ">= 2.3.5" +gem 'jeweler', '~> 2.3' +gem 'rdoc', '~> 6.14' +gem 'test-unit', '~> 3.6' # Add dependencies to develop your gem here. # Include everything needed to run rake, tests, features, etc. group :development do - gem "shoulda", ">= 0" - gem "bundler" - gem "rcov", ">= 0" + gem 'rake', '~> 13.2' + gem 'shoulda', '~> 3.6' + gem 'simplecov', '>= 0' end diff --git a/Gemfile.lock b/Gemfile.lock index b3fbc40..0caa8ad 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,34 +1,125 @@ GEM remote: http://rubygems.org/ specs: - activesupport (3.0.1) - colorize (0.5.8) - coveralls (0.6.7) - colorize + activesupport (8.0.2) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + addressable (2.4.0) + base64 (0.2.0) + benchmark (0.4.0) + bigdecimal (3.1.9) + builder (3.3.0) + byebug (12.0.0) + concurrent-ruby (1.3.5) + connection_pool (2.5.3) + date (3.4.1) + descendants_tracker (0.0.4) + thread_safe (~> 0.3, >= 0.3.1) + docile (1.4.1) + drb (2.2.1) + erb (5.0.1) + faraday (0.9.2) + multipart-post (>= 1.2, < 3) + git (1.11.0) + rchardet (~> 1.8) + github_api (0.16.0) + addressable (~> 2.4.0) + descendants_tracker (~> 0.0.4) + faraday (~> 0.8, < 0.10) + hashie (>= 3.4) + mime-types (>= 1.16, < 3.0) + oauth2 (~> 1.0) + hashie (5.0.0) + highline (3.1.2) + reline + i18n (1.14.7) + concurrent-ruby (~> 1.0) + io-console (0.8.0) + jeweler (2.3.9) + builder + bundler + git (>= 1.2.5) + github_api (~> 0.16.0) + highline (>= 1.6.15) + nokogiri (>= 1.5.10) + psych + rake + rdoc + semver2 + jwt (2.10.1) + base64 + logger (1.7.0) + mime-types (2.99.3) + minitest (5.25.5) + multi_json (1.15.0) + multi_xml (0.7.2) + bigdecimal (~> 3.1) + multipart-post (2.4.1) + nokogiri (1.18.8-x86_64-linux-gnu) + racc (~> 1.4) + oauth2 (1.4.8) + faraday (>= 0.8, < 3.0) + jwt (>= 1.0, < 3.0) multi_json (~> 1.3) - rest-client - simplecov (>= 0.7) - thor - i18n (0.4.2) - mime-types (1.23) - multi_json (1.7.2) - rcov (0.9.9) - rest-client (1.6.7) - mime-types (>= 1.16) - shoulda (2.11.3) - simplecov (0.7.1) - multi_json (~> 1.0) - simplecov-html (~> 0.7.1) - simplecov-html (0.7.1) - thor (0.18.1) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + power_assert (2.0.5) + psych (5.2.6) + date + stringio + racc (1.8.1) + rack (2.2.15) + rake (13.2.1) + rchardet (1.9.0) + rdoc (6.14.0) + erb + psych (>= 4.0.0) + reline (0.6.1) + io-console (~> 0.5) + securerandom (0.4.1) + semver2 (3.4.2) + shoulda (3.6.0) + shoulda-context (~> 1.0, >= 1.0.1) + shoulda-matchers (~> 3.0) + shoulda-context (1.2.2) + shoulda-matchers (3.1.3) + activesupport (>= 4.0.0) + simplecov (0.22.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.13.1) + simplecov_json_formatter (0.1.4) + stringio (3.1.7) + test-unit (3.6.8) + power_assert + thread_safe (0.3.6) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uri (1.0.3) PLATFORMS - ruby + x86_64-linux DEPENDENCIES - activesupport - bundler - coveralls + byebug (~> 12.0) i18n - rcov - shoulda + jeweler (~> 2.3) + rake (~> 13.2) + rdoc (~> 6.14) + shoulda (~> 3.6) + simplecov + test-unit (~> 3.6) + +BUNDLED WITH + 2.6.8 diff --git a/Rakefile b/Rakefile index 7191e47..c52bd94 100644 --- a/Rakefile +++ b/Rakefile @@ -26,6 +26,9 @@ Jeweler::Tasks.new do |gem| end Jeweler::RubygemsDotOrgTasks.new +require 'simplecov' +SimpleCov.start + require 'rake/testtask' Rake::TestTask.new(:test) do |test| test.libs << 'lib' << 'test' @@ -33,16 +36,9 @@ Rake::TestTask.new(:test) do |test| test.verbose = true end -require 'rcov/rcovtask' -Rcov::RcovTask.new do |test| - test.libs << 'test' - test.pattern = 'test/**/test_*.rb' - test.verbose = true -end - task :default => :test -require 'rake/rdoctask' +require 'rdoc/task' Rake::RDocTask.new do |rdoc| version = File.exist?('VERSION') ? File.read('VERSION') : "" diff --git a/lib/time_diff.rb b/lib/time_diff.rb index 968cadb..aebb617 100644 --- a/lib/time_diff.rb +++ b/lib/time_diff.rb @@ -1,13 +1,25 @@ -require 'rubygems' -require 'active_support/all' +# require 'active_support/time' require 'i18n' class Time + SECONDS_PER = { + 'year' => 365 * 86_400, # Leap years are accounted for in the days part + 'month' => 86_400 * 30, + 'week' => 86_400 * 7, + 'day' => 86_400, + 'hour' => 3600, + 'minute' => 60, + 'second' => 1 + }.freeze + def self.diff(start_date, end_date, format_string='%y, %M, %w, %d and %h:%m:%s') - #I18n.load_path += Dir.glob("lib/*.yml") + I18n.available_locales = [:en] + I18n.default_locale = :en +#I18n.load_path += Dir.glob("lib/*.yml") start_time = start_date.to_time if start_date.respond_to?(:to_time) end_time = end_date.to_time if end_date.respond_to?(:to_time) distance_in_seconds = ((end_time - start_time).abs).round + # byebg components = get_time_diff_components(%w(year month week day hour minute second), distance_in_seconds) time_diff_components = {:year => components[0], :month => components[1], :week => components[2], :day => components[3], :hour => components[4], :minute => components[5], :second => components[6]} @@ -46,9 +58,9 @@ def self.create_formatted_component_hash(components, formatted_intervals) def self.get_time_diff_components(intervals, distance_in_seconds) components = [] intervals.each do |interval| - component = (distance_in_seconds / 1.send(interval)).floor - distance_in_seconds -= component.send(interval) - components << component + component = (distance_in_seconds / SECONDS_PER[interval]).floor + distance_in_seconds -= component * SECONDS_PER[interval] + components << component end components end @@ -68,7 +80,7 @@ def Time.format_date_time(time_diff_components, format_string) end def Time.pluralize(word, count) - return count != 1 ? I18n.t(word.pluralize, :default => word.pluralize) : I18n.t(word, :default => word) + return count != 1 ? I18n.t("#{word}s", :default => "#{word}s") : I18n.t(word, :default => word) end def Time.remove_format_string_for_zero_components(time_diff_components, format_string) diff --git a/test/test_time_diff.rb b/test/test_time_diff.rb index e4957e2..2685832 100644 --- a/test/test_time_diff.rb +++ b/test/test_time_diff.rb @@ -2,28 +2,29 @@ require 'time' class TestTimeDiff < Test::Unit::TestCase - should "return the time differnce in displayable format" do + should 'return the time difference in displayable format' do assert_test_scenarios(Time.parse('2011-03-06'), Time.parse('2011-03-07'), {:year => 0, :month => 0, :week => 0, :day => 1, :hour => 0, :minute => 0, :second => 0, :diff => '1 day and 00:00:00'}) assert_test_scenarios(Time.parse('2011-03-06'), Time.parse('2011-04-08'), {:year => 0, :month => 1, :week => 0, :day => 3, :hour => 0, :minute => 0, :second => 0, :diff => '1 month, 3 days and 00:00:00'}) assert_test_scenarios(Time.parse('2011-03-06 12:30:00'), Time.parse('2011-03-07 12:30:30'), {:year => 0, :month => 0, :week => 0, :day => 1, :hour => 0, :minute => 0, :second => 30, :diff => '1 day and 00:00:30'}) - assert_test_scenarios(Time.parse('2011-03-06'), Time.parse('2013-03-07'), {:year => 2, :month => 0, :week => 0, :day => 1, :hour => 12, :minute => 0, :second => 0, :diff => '2 years, 1 day and 12:00:00'}) + assert_test_scenarios(Time.parse('2011-03-06'), Time.parse('2013-03-07'), {:year => 2, :month => 0, :week => 0, :day => 2, :hour => 0, :minute => 0, :second => 0, :diff => '2 years, 2 days and 00:00:00'}) assert_test_scenarios(Time.parse('2011-03-06'), Time.parse('2011-03-14'), {:year => 0, :month => 0, :week => 1, :day => 1, :hour => 0, :minute => 0, :second => 0, :diff => '1 week, 1 day and 00:00:00'}) assert_test_scenarios(Time.parse('2011-03-06 12:30:00'), Time.parse('2011-03-06 12:30:30'), {:year => 0, :month => 0, :week => 0, :day => 0, :hour => 0, :minute => 0, :second => 30, :diff => '00:00:30'}) end - should "return the time difference in a formatted text" do - assert_test_scenarios_for_formatted_diff(Time.parse('2010-03-06 12:30:00'), Time.parse('2011-03-07 12:30:30'), '%y, %d and %h:%m:%s', '1 year and 18:00:30') + should 'return the time difference in a formatted text' do + # 2012 was a leap year + assert_test_scenarios_for_formatted_diff(Time.parse('2011-03-06 12:30:00'), Time.parse('2012-03-07 12:30:30'), '%y, %d and %h:%m:%s', '1 year, 2 days and 00:00:30') assert_test_scenarios_for_formatted_diff(Time.parse('2010-03-06 12:30:00'), Time.parse('2011-03-07 12:30:30'), '%d %H %N %S', '366 days 0 hours 0 minutes 30 seconds') assert_test_scenarios_for_formatted_diff(Time.parse('2011-03-06 12:30:00'), Time.parse('2011-03-07 12:30:30'), '%H %N %S', '24 hours 0 minutes 30 seconds') end def assert_test_scenarios(start_date, end_date, expected_result) date_diff = Time.diff(start_date, end_date) - assert_equal(date_diff, expected_result) + assert_equal(expected_result, date_diff) end def assert_test_scenarios_for_formatted_diff(start_date, end_date, format_string, expected_result) date_diff = Time.diff(start_date, end_date, format_string) - assert_equal(date_diff[:diff], expected_result) + assert_equal(expected_result, date_diff[:diff]) end end From dadf2ec486014b0d9b4164a6a4e06cb97c207436 Mon Sep 17 00:00:00 2001 From: Arnaud Meuret Date: Tue, 20 May 2025 21:41:01 +0900 Subject: [PATCH 2/2] Fix elimination of zero components Debugged the existing approach but this leaves to be desired when days aren't 0 and hours or minutes are. --- lib/time_diff.rb | 7 ++++--- test/test_time_diff.rb | 6 ++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/time_diff.rb b/lib/time_diff.rb index aebb617..6255e7e 100644 --- a/lib/time_diff.rb +++ b/lib/time_diff.rb @@ -1,3 +1,4 @@ +require 'rubygems' # require 'active_support/time' require 'i18n' @@ -84,12 +85,12 @@ def Time.pluralize(word, count) end def Time.remove_format_string_for_zero_components(time_diff_components, format_string) - [{:year => '%y'}, {:month => '%M'}, {:week => '%w'}].each do |component| + [{minute: '%N'}, {hour: '%H'}, {:year => '%y'}, {:month => '%M'}, {:week => '%w'}].each do |component| key = component.keys.first value = component.values.first - format_string.gsub!("#{value}, ",'') if time_diff_components[key] == 0 + format_string.gsub!(/#{value},?\s?/,'') if time_diff_components[key].nil? || time_diff_components[key].zero? end - if time_diff_components[:day] == 0 + if time_diff_components[:day].nil? || time_diff_components[:day].zero? (format_string.slice(0..1) == '%d')? format_string.gsub!('%d ','') : format_string.gsub!(', %d','') end format_string.slice!(0..3) if format_string.slice(0..3) == 'and ' diff --git a/test/test_time_diff.rb b/test/test_time_diff.rb index 2685832..7502fdb 100644 --- a/test/test_time_diff.rb +++ b/test/test_time_diff.rb @@ -14,8 +14,10 @@ class TestTimeDiff < Test::Unit::TestCase should 'return the time difference in a formatted text' do # 2012 was a leap year assert_test_scenarios_for_formatted_diff(Time.parse('2011-03-06 12:30:00'), Time.parse('2012-03-07 12:30:30'), '%y, %d and %h:%m:%s', '1 year, 2 days and 00:00:30') - assert_test_scenarios_for_formatted_diff(Time.parse('2010-03-06 12:30:00'), Time.parse('2011-03-07 12:30:30'), '%d %H %N %S', '366 days 0 hours 0 minutes 30 seconds') - assert_test_scenarios_for_formatted_diff(Time.parse('2011-03-06 12:30:00'), Time.parse('2011-03-07 12:30:30'), '%H %N %S', '24 hours 0 minutes 30 seconds') + # assert_test_scenarios_for_formatted_diff(Time.parse('2010-03-06 12:30:00'), Time.parse('2011-03-07 12:30:30'), '%d %H %N %S', '366 days 0 hours 0 minutes 30 seconds') + assert_test_scenarios_for_formatted_diff(Time.parse('2010-03-06 12:30:00'), Time.parse('2011-03-07 12:30:30'), '%d %H %N %S', '366 days 30 seconds') + assert_test_scenarios_for_formatted_diff(Time.parse('2010-03-06 12:30:00'), Time.parse('2010-03-06 12:35:30'), '%d %H %N %S', '5 minutes 30 seconds') + assert_test_scenarios_for_formatted_diff(Time.parse('2011-03-06 12:30:00'), Time.parse('2011-03-07 12:30:30'), '%H %N %S', '24 hours 30 seconds') end def assert_test_scenarios(start_date, end_date, expected_result)