Project

General

Profile

Actions

Defect #40914

open

Rounding error in my/page -> timelog

Added by Boris Brodski 5 days ago. Updated 23 minutes ago.

Status:
Confirmed
Priority:
Normal
Assignee:
-
Category:
Time tracking
Target version:
-
Start date:
Due date:
% Done:

0%

Estimated time:
Resolution:
Affected version:

Description

On the page my/page, if the timelog is displayed, the total is shown at the top of the table. The summing is not correctly implemented, leading to rounding errors.

Reproduction and Example:

  1. Add time entries for one day, one issue:
    - 0:10
    - 0:40
    - 0:10
  2. Navigate to my/page
  3. Add the 'timelog' widget if it is not already present.
  4. The time entries should be shown. The total displayed is 1:01.

Implementation and Easy Fix:

Current implementation (app/views/my/blocks/_timelog.html.erb:45):

html_hours(format_hours(entries_by_day[day].sum(&:hours)))

Summing hours introduces rounding errors. To fix this, convert to minutes first:

html_hours(format_hours(entries_by_day[day].map{|t| (t.hours * 60).to_i}.sum / 60))

Files


Related issues

Related to Redmine - Defect #36897: Wrong formatting of date in Time EntriesConfirmed

Actions
Actions #1

Updated by Boris Brodski 5 days ago

In the same way the <h3>..</h3> tag should be fixed:

Current implementation (app/views/my/blocks/_timelog.html.erb:7):

l_hours_short entries.sum(&:hours)

Fix:

l_hours_short(entries.map{|t| (t.hours * 60).to_i}.sum / 60)
Actions #2

Updated by Go MAEDA 3 days ago

  • Status changed from New to Confirmed
Actions #3

Updated by Go MAEDA about 1 hour ago

Here is another solution. This patch will likely also fix the issue reported in #36897.

diff --git a/lib/redmine/i18n.rb b/lib/redmine/i18n.rb
index 83ecb05eb..52221029f 100644
--- a/lib/redmine/i18n.rb
+++ b/lib/redmine/i18n.rb
@@ -93,8 +93,9 @@ module Redmine
       return "" if hours.blank?

       if Setting.timespan_format == 'minutes'
-        h = hours.floor
-        m = ((hours - h) * 60).round
+        rational_hours = hours.rationalize(Rational('1/60'))
+        h = rational_hours.truncate
+        m = ((rational_hours - h) * 60).round
         "%d:%02d" % [h, m]
       else
         number_with_delimiter(sprintf('%.2f', hours.to_f), delimiter: nil)

Actions #4

Updated by Go MAEDA 23 minutes ago

Go MAEDA wrote in #note-3:

Here is another solution. This patch will likely also fix the issue reported in #36897.

[...]

Sorry, using rationalize(Rational('1/60')) (approximation in minutes) breaks some tests. rationalize(Rational('1/3600')) (approximation in seconds) works fine.

Failure:
TimelogReportTest#test_report_all_time_by_day [test/functional/timelog_report_test.rb:87]:
Expected: "162:54" 
  Actual: "162:53".
Expected 0 to be >= 1.

bin/rails test test/functional/timelog_report_test.rb:84
diff --git a/lib/redmine/i18n.rb b/lib/redmine/i18n.rb
index 83ecb05eb..40b991f8a 100644
--- a/lib/redmine/i18n.rb
+++ b/lib/redmine/i18n.rb
@@ -93,8 +93,9 @@ module Redmine
       return "" if hours.blank?

       if Setting.timespan_format == 'minutes'
-        h = hours.floor
-        m = ((hours - h) * 60).round
+        rational_hours = hours.rationalize(Rational('1/3600'))
+        h = rational_hours.truncate
+        m = ((rational_hours - h) * 60).round
         "%d:%02d" % [h, m]
       else
         number_with_delimiter(sprintf('%.2f', hours.to_f), delimiter: nil)
Actions #5

Updated by Go MAEDA 19 minutes ago

  • Related to Defect #36897: Wrong formatting of date in Time Entries added
Actions

Also available in: Atom PDF