Skip to content

Commit

Permalink
Add :eta_time token to display the estimated time of day at completion
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrmurach committed Jan 5, 2021
1 parent dd8fe57 commit 35bc489
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* Add Multi#done? to check if all bar are stopped or finished
* Add indeterminate progress support when no total is given
* Add :bar_format option to allow selecting preconfigured bar displays
* Add :eta_time format token to display the estimated time of day at completion

### Changed
* Change Multi#stopped? to check that all bars are stopped
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ These are the tokens that are currently supported:
* `:percent` the completion percentage
* `:elapsed` the elapsed time in seconds
* `:eta` the estimated time to completion in seconds
* `:eta_time` the estimated time of day at completion
* `:rate` the current rate of progression per second
* `:byte_rate` the current rate of progression in bytes per second
* `:mean_rate` the averaged rate of progression per second
Expand Down
37 changes: 37 additions & 0 deletions lib/tty/progressbar/formatter/estimated_time.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

module TTY
class ProgressBar
# Used by {Pipeline} to foramt :eta_time token
#
# @api private
class EstimatedTimeFormatter
include TTY::ProgressBar::Formatter[/:eta_time/.freeze]

# Format :eta_time token
#
# @param [String] value
# the value to format
#
# @api public
def format(value)
if @progress.indeterminate?
return value.gsub(matcher, "--:--:--")
end

elapsed = Time.now - @progress.start_at
estimated = (elapsed / @progress.ratio).to_f - elapsed
estimated = (estimated.infinite? || estimated < 0) ? 0.0 : estimated

time_format = if estimated >= 86_400 # longer than a day
"%Y-%m-%d %H:%M:%S"
else
"%H:%M:%S"
end
completion_time = Time.now + estimated
eta_time = completion_time.strftime(time_format)
value.gsub(matcher, eta_time)
end
end # EstimatedTimeFormatter
end # ProgressBar
end # TTY
2 changes: 2 additions & 0 deletions lib/tty/progressbar/formatters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
require_relative "formatter/current_byte"
require_relative "formatter/elapsed"
require_relative "formatter/estimated"
require_relative "formatter/estimated_time"
require_relative "formatter/percent"
require_relative "formatter/rate"
require_relative "formatter/byte_rate"
Expand Down Expand Up @@ -37,6 +38,7 @@ def load(progress)
@pipeline.use TTY::ProgressBar::TotalFormatter.new(progress)
@pipeline.use TTY::ProgressBar::TotalByteFormatter.new(progress)
@pipeline.use TTY::ProgressBar::ElapsedFormatter.new(progress)
@pipeline.use TTY::ProgressBar::EstimatedTimeFormatter.new(progress)
@pipeline.use TTY::ProgressBar::EstimatedFormatter.new(progress)
@pipeline.use TTY::ProgressBar::PercentFormatter.new(progress)
@pipeline.use TTY::ProgressBar::ByteFormatter.new(progress)
Expand Down
71 changes: 71 additions & 0 deletions spec/unit/formatter/estimated_time_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# frozen_string_literal: true

RSpec.describe TTY::ProgressBar, ":eta_time token" do
let(:output) { StringIO.new }

it "displays estimated completion time of day" do
time_now = Time.local(2020, 1, 5, 12, 0, 0)
Timecop.freeze(time_now)
bar = described_class.new(" :eta_time", output: output, total: 5)

5.times do |sec|
time_now = Time.local(2020, 1, 5, 12, 0, sec)
Timecop.freeze(time_now)
bar.advance
end

output.rewind
expect(output.read).to eq([
"\e[1G 12:00:00",
"\e[1G 12:00:02",
"\e[1G 12:00:03",
"\e[1G 12:00:03",
"\e[1G 12:00:04\n"
].join)
Timecop.return
end

it "displays estimated completion time of day with date after 24 hours" do
time_now = Time.local(2020, 1, 5, 12, 0, 0)
Timecop.freeze(time_now)
bar = described_class.new(" :eta_time", output: output, total: 5)

2.times do |day|
time_now = Time.local(2020, 1, day + 6, 12, 0, 0)
Timecop.freeze(time_now)
bar.advance
end

output.rewind
expect(output.read).to eq([
"\e[1G 12:00:00",
"\e[1G 2020-01-09 00:00:00",
].join)
Timecop.return
end

it "displays unknown estimated completion time of day as --:--:--" do
time_now = Time.local(2020, 1, 5, 12, 0, 0)
Timecop.freeze(time_now)
bar = described_class.new(" :eta_time", output: output, total: nil)

3.times { bar.advance }
bar.update(total: 5)

2.times do |sec|
time_now = Time.local(2020, 1, 5, 12, 0, sec)
Timecop.freeze(time_now)
bar.advance
end

output.rewind
expect(output.read).to eq([
"\e[1G --:--:--",
"\e[1G --:--:--",
"\e[1G --:--:--",
"\e[1G 12:00:00",
"\e[1G 12:00:01\n"
].join)
Timecop.return
end
end

0 comments on commit 35bc489

Please sign in to comment.