88miles 1.0.1

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.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ gem "trollop", "~> 2.0"
3
+ gem "highline", "~> 1.6.19"
4
+ gem "oauth2", "~> 0.9.2i"
5
+ gem "launchy", "~> 2.3.0"
6
+ gem "terminal-table", "~> 1.4.5"
7
+
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "rdoc", "~> 3.12"
11
+ gem "bundler", "~> 1.0"
12
+ gem "jeweler", "~> 1.8.7"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,81 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (4.0.0)
5
+ i18n (~> 0.6, >= 0.6.4)
6
+ minitest (~> 4.2)
7
+ multi_json (~> 1.3)
8
+ thread_safe (~> 0.1)
9
+ tzinfo (~> 0.3.37)
10
+ addressable (2.3.5)
11
+ atomic (1.1.14)
12
+ builder (3.2.2)
13
+ faraday (0.8.8)
14
+ multipart-post (~> 1.2.0)
15
+ git (1.2.6)
16
+ github_api (0.10.1)
17
+ addressable
18
+ faraday (~> 0.8.1)
19
+ hashie (>= 1.2)
20
+ multi_json (~> 1.4)
21
+ nokogiri (~> 1.5.2)
22
+ oauth2
23
+ hashie (2.0.5)
24
+ highline (1.6.19)
25
+ httpauth (0.2.0)
26
+ i18n (0.6.5)
27
+ jeweler (1.8.7)
28
+ builder
29
+ bundler (~> 1.0)
30
+ git (>= 1.2.5)
31
+ github_api (= 0.10.1)
32
+ highline (>= 1.6.15)
33
+ nokogiri (= 1.5.10)
34
+ rake
35
+ rdoc
36
+ json (1.8.0)
37
+ jwt (0.1.8)
38
+ multi_json (>= 1.5)
39
+ launchy (2.3.0)
40
+ addressable (~> 2.3)
41
+ minitest (4.7.5)
42
+ multi_json (1.8.1)
43
+ multi_xml (0.5.5)
44
+ multipart-post (1.2.0)
45
+ nokogiri (1.5.10)
46
+ oauth2 (0.9.2)
47
+ faraday (~> 0.8)
48
+ httpauth (~> 0.2)
49
+ jwt (~> 0.1.4)
50
+ multi_json (~> 1.0)
51
+ multi_xml (~> 0.5)
52
+ rack (~> 1.2)
53
+ rack (1.5.2)
54
+ rake (10.1.0)
55
+ rdoc (3.12.2)
56
+ json (~> 1.4)
57
+ shoulda (3.5.0)
58
+ shoulda-context (~> 1.0, >= 1.0.1)
59
+ shoulda-matchers (>= 1.4.1, < 3.0)
60
+ shoulda-context (1.1.5)
61
+ shoulda-matchers (2.4.0)
62
+ activesupport (>= 3.0.0)
63
+ terminal-table (1.4.5)
64
+ thread_safe (0.1.3)
65
+ atomic
66
+ trollop (2.0)
67
+ tzinfo (0.3.37)
68
+
69
+ PLATFORMS
70
+ ruby
71
+
72
+ DEPENDENCIES
73
+ bundler (~> 1.0)
74
+ highline (~> 1.6.19)
75
+ jeweler (~> 1.8.7)
76
+ launchy (~> 2.3.0)
77
+ oauth2 (~> 0.9.2i)
78
+ rdoc (~> 3.12)
79
+ shoulda
80
+ terminal-table (~> 1.4.5)
81
+ trollop (~> 2.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 MadPilot Productions
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # 88 Miles Command Line Application
2
+
3
+ 88 Miles is simple time tracking for freelance developers, designers and copywriters. This gem allows you to access you account from your command line.
4
+
5
+ To use this gem, you will need an 88 Miles account. You can [register here](http://88miles.net)
6
+
7
+ ## Installation
8
+
9
+ gem install 88miles
10
+
11
+ ## Get started
12
+
13
+ First, you will need to give the gem access to 88 Miles. This is done via OAuth, so you don't need to ever store your login or password.
14
+
15
+ To setup the link:
16
+
17
+ 88miles setup
18
+
19
+ If you on a computer has a default browser, it will open a browser window asking you to login, and approve access to the application.
20
+
21
+ Once authentication has happened, you will be redirected to a confirmation window. Cut and paste the URL from this window in to the console that you started the process.
22
+
23
+ ## Linking a Project to a directory
24
+
25
+ The command line application links directories with projects in 88 Miles. To setup the link, run
26
+
27
+ 88miles init [path/to/directory]
28
+
29
+ You will be presented with a list of projects to select from. Select a project, and the link is complete.
30
+
31
+ ## Punching in
32
+
33
+ Once you have linked a project, you can punch in by:
34
+
35
+ 88miles start
36
+
37
+ If you want to select an activity:
38
+
39
+ 88miles start -a
40
+
41
+ You will be presented with a list of activities from which you can select from
42
+
43
+ ## Punching out
44
+
45
+ To punch out of the linked project
46
+
47
+ 88miles stop -n "Any notes to associate with shift"
48
+
49
+ ## View the current status of the project
50
+
51
+ You can see how much time you have clocked against a project by:
52
+
53
+ 88miles status
54
+
55
+ If you want to have it automatically update, you can leave it in the foreground
56
+
57
+ 88miles status -f
58
+
59
+ Hit Ctrl-C to exit foreground mode.
60
+
61
+ ## List all shifts
62
+
63
+ If you want to view a list of all the shifts clocked against the linked project:
64
+
65
+ 88miles log
66
+
67
+ To format it in a nice table view:
68
+
69
+ 88miles log -t
70
+
71
+ ## Update the local cache
72
+
73
+ To speed things up, your company, project and staff list is cached locally. If you modify any of these things on the website, you'll need to re-sync the cache by:
74
+
75
+ 88miles sync
76
+
77
+ ## Copyright
78
+
79
+ Copyright (c) 2013 [MadPilot Productions](http://www.madpilot.com.au/). See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "88miles"
18
+ gem.homepage = "http://github.com/madpilot/gigawatt"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Command line interface to 88 Miles}
21
+ gem.description = %Q{88 Miles (http://88miles.net) is simple time tracking for freelance developers, designers and copywriters. This gem allows you to access you account from your command line.}
22
+ gem.email = "myles@madpilot.com.au"
23
+ gem.authors = ["Myles Eftos"]
24
+ gem.executables = [ '88miles' ]
25
+ # dependencies defined in Gemfile
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rake/testtask'
30
+ Rake::TestTask.new(:test) do |test|
31
+ test.libs << 'lib' << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+
36
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.1
data/bin/88miles ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'gigawatt'
3
+ exit Gigawatt::Application.run!
data/gigawatt.gemspec ADDED
@@ -0,0 +1,89 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "gigawatt"
8
+ s.version = "1.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Myles Eftos"]
12
+ s.date = "2013-10-06"
13
+ s.description = "88 Miles (http://88miles.net) is simple time tracking for freelance developers, designers and copywriters. This gem allows you to access you account from your command line."
14
+ s.email = "myles@madpilot.com.au"
15
+ s.executables = ["88miles"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt",
18
+ "README.md"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.md",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/88miles",
29
+ "gigawatt.gemspec",
30
+ "lib/gigawatt.rb",
31
+ "lib/gigawatt/application.rb",
32
+ "lib/gigawatt/cache.rb",
33
+ "lib/gigawatt/commands/init.rb",
34
+ "lib/gigawatt/commands/log.rb",
35
+ "lib/gigawatt/commands/setup.rb",
36
+ "lib/gigawatt/commands/start.rb",
37
+ "lib/gigawatt/commands/status.rb",
38
+ "lib/gigawatt/commands/stop.rb",
39
+ "lib/gigawatt/commands/sync.rb",
40
+ "lib/gigawatt/oauth.rb",
41
+ "lib/gigawatt/options.rb",
42
+ "lib/gigawatt/project_file.rb",
43
+ "lib/gigawatt/settings.rb",
44
+ "test/helper.rb",
45
+ "test/test_gigawatt.rb"
46
+ ]
47
+ s.homepage = "http://github.com/madpilot/gigawatt"
48
+ s.licenses = ["MIT"]
49
+ s.require_paths = ["lib"]
50
+ s.rubygems_version = "1.8.15"
51
+ s.summary = "Command line interface to 88 Miles"
52
+
53
+ if s.respond_to? :specification_version then
54
+ s.specification_version = 3
55
+
56
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
57
+ s.add_runtime_dependency(%q<trollop>, ["~> 2.0"])
58
+ s.add_runtime_dependency(%q<highline>, ["~> 1.6.19"])
59
+ s.add_runtime_dependency(%q<oauth2>, ["~> 0.9.2i"])
60
+ s.add_runtime_dependency(%q<launchy>, ["~> 2.3.0"])
61
+ s.add_runtime_dependency(%q<terminal-table>, ["~> 1.4.5"])
62
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
63
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
64
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
65
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.7"])
66
+ else
67
+ s.add_dependency(%q<trollop>, ["~> 2.0"])
68
+ s.add_dependency(%q<highline>, ["~> 1.6.19"])
69
+ s.add_dependency(%q<oauth2>, ["~> 0.9.2i"])
70
+ s.add_dependency(%q<launchy>, ["~> 2.3.0"])
71
+ s.add_dependency(%q<terminal-table>, ["~> 1.4.5"])
72
+ s.add_dependency(%q<shoulda>, [">= 0"])
73
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
74
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
75
+ s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
76
+ end
77
+ else
78
+ s.add_dependency(%q<trollop>, ["~> 2.0"])
79
+ s.add_dependency(%q<highline>, ["~> 1.6.19"])
80
+ s.add_dependency(%q<oauth2>, ["~> 0.9.2i"])
81
+ s.add_dependency(%q<launchy>, ["~> 2.3.0"])
82
+ s.add_dependency(%q<terminal-table>, ["~> 1.4.5"])
83
+ s.add_dependency(%q<shoulda>, [">= 0"])
84
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
85
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
86
+ s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
87
+ end
88
+ end
89
+
@@ -0,0 +1,8 @@
1
+ module Gigawatt
2
+ class Application
3
+ def self.run!
4
+ trap("SIGINT") { puts " "; exit! }
5
+ Options.parse!
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,71 @@
1
+ module Gigawatt
2
+ class Cache
3
+ def initialize(settings, access_key)
4
+ @access_key = access_key
5
+ @settings = settings
6
+ end
7
+
8
+ def fetch_companies
9
+ companies = JSON.parse(@access_key.get('/api/1/companies.json').body)
10
+ companies["response"]
11
+ end
12
+
13
+ def fetch_projects
14
+ projects = JSON.parse(@access_key.get("/api/1/projects.json?where=#{URI::encode('active="true"')}").body)
15
+ projects["response"]
16
+ end
17
+
18
+ def fetch_staff
19
+ staff = JSON.parse(@access_key.get("/api/1/staff.json").body)
20
+ staff["response"]
21
+ end
22
+
23
+ def refresh!
24
+ @settings.companies = nil
25
+ @settings.projects = nil
26
+ @settings.staff = nil
27
+ companies
28
+ projects
29
+ staff
30
+ end
31
+
32
+ def companies(indexed = false)
33
+ if @settings.companies.nil?
34
+ @settings.companies = fetch_companies
35
+ @settings.write(:companies)
36
+ end
37
+ return @settings.companies unless indexed
38
+ companies = {}
39
+ @settings.companies.each do |c|
40
+ companies[c["uuid"]] = c
41
+ end
42
+ companies
43
+ end
44
+
45
+ def projects(indexed = false)
46
+ if @settings.projects.nil?
47
+ @settings.projects = fetch_projects
48
+ @settings.write(:projects)
49
+ end
50
+ return @settings.projects unless indexed
51
+ projects = {}
52
+ @settings.projects.each do |p|
53
+ projects[p["uuid"]] = p
54
+ end
55
+ projects
56
+ end
57
+
58
+ def staff(indexed = false)
59
+ if @settings.staff.nil?
60
+ @settings.staff = fetch_staff
61
+ @settings.write(:staff)
62
+ end
63
+ return @settings.staff unless indexed
64
+ staff = {}
65
+ @settings.staff.each do |s|
66
+ staff[s["uuid"]] = s
67
+ end
68
+ staff
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,51 @@
1
+ module Gigawatt
2
+ module Commands
3
+ class Init
4
+ attr_accessor :options
5
+
6
+ def self.run!(settings)
7
+ directory = nil
8
+ p = Trollop::Parser.new
9
+ options = p.parse
10
+ directory = p.leftovers.first
11
+
12
+ Trollop::die "Please supply a directory" unless directory
13
+ Trollop::die "Directory does not exist" unless File.exists?(directory)
14
+ Trollop::die "#{directory} is not a directory" unless File.directory?(directory)
15
+
16
+ instance = self.new(settings, options, directory)
17
+ begin
18
+ instance.list_projects
19
+ rescue OAuth2::Error => e
20
+ say "Access to your 88 Miles may have been revoked. Please run <%= color('88miles setup', BOLD) %> again."
21
+ return INVALID_OAUTH_TOKEN_EXIT_CODE
22
+ end
23
+
24
+ return OK_EXIT_CODE
25
+ end
26
+
27
+ def initialize(settings, options, directory)
28
+ @settings = settings
29
+ @options = options
30
+ @directory = directory
31
+ @access_key = OAuth.token(settings.access_key)
32
+ @cache = Cache.new(settings, @access_key)
33
+ end
34
+
35
+ def list_projects
36
+ companies = @cache.companies(true)
37
+
38
+ selected = nil
39
+ choose do |menu|
40
+ menu.prompt = "Pick a project"
41
+ @cache.projects.each do |project|
42
+ menu.choice("#{companies[project["company_uuid"]]["name"]}: #{project["name"]}") { selected = project }
43
+ end
44
+ end
45
+
46
+ ProjectFile.write(selected)
47
+ say("<%= color('#{companies[selected["company_uuid"]]["name"]}: #{selected["name"]}', GREEN) %> selected. Run <%= color('88miles start', BOLD) %> to punch in")
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,162 @@
1
+ module Gigawatt
2
+ module Commands
3
+ class Log
4
+ attr_accessor :options
5
+
6
+ def self.run!(settings)
7
+ options = Trollop::options do
8
+ banner <<-EOS
9
+ 88 Miles Command line application - http://88miles.net
10
+
11
+ Print out the shifts for the linked project
12
+
13
+ Usage:
14
+ 88miles log [options]
15
+
16
+ options
17
+ EOS
18
+ opt :page, "Page the output", :type => :flag, :default => true
19
+ opt :table, "Outputs a formatted table", :type => :flag, :default => false
20
+ end
21
+
22
+ instance = self.new(settings, options)
23
+ begin
24
+ return instance.log
25
+ rescue OAuth2::Error => e
26
+ say "Access to your 88 Miles may have been revoked. Please run <%= color('88miles setup', BOLD) %> again."
27
+ return INVALID_OAUTH_TOKEN_EXIT_CODE
28
+ end
29
+ end
30
+
31
+ def initialize(settings, options)
32
+ @settings = settings
33
+ @options = options
34
+
35
+ @access_key = OAuth.token(@settings.access_key)
36
+ @cache = Cache.new(settings, @access_key)
37
+ @project = Gigawatt::ProjectFile.new.project
38
+ end
39
+
40
+ def log
41
+ unless @project
42
+ say("No project found.")
43
+ return NO_PROJECT_EXIT_CODE
44
+ end
45
+
46
+ $terminal.page_at = :auto if @options[:page]
47
+
48
+ if @options[:table]
49
+ log_table
50
+ else
51
+ log_blob
52
+ end
53
+ return OK_EXIT_CODE
54
+ end
55
+
56
+ def log_blob
57
+ buffer = ''
58
+ shifts = JSON.parse(@access_key.get("/api/1/projects/#{@project["uuid"]}/shifts.json").body)
59
+
60
+ company = @cache.companies(true)[@project["company_uuid"]]
61
+ staff = @cache.staff(true)
62
+ buffer += "#{company["name"]}: #{@project["name"]} shifts:\n\n"
63
+
64
+ total = 0
65
+ rows = []
66
+ str = ""
67
+ shifts["response"].each do |shift|
68
+ staff_member = staff[shift["user_uuid"]]
69
+ start = Time.parse(shift["start"])
70
+ stop = Time.parse(shift["stop"] || Time.now.to_s)
71
+ total += (stop - start)
72
+
73
+ str += "<%= color('uuid #{shift["uuid"]}', YELLOW) %>\n"
74
+
75
+ if staff_member
76
+ str += "Staff: #{staff_member["first_name"]} #{staff_member["last_name"]} <#{staff_member["email_address"]}>\n"
77
+ else
78
+ str += "Staff: [Deleted user]\n"
79
+ end
80
+
81
+ str += "Start: #{start.getlocal.strftime('%c %:z')}\n"
82
+ str += "Stop: #{stop.getlocal.strftime('%c %:z')}\n"
83
+ str += "Total: #{to_clock_s(stop - start)}\n"
84
+ str += "\n\t"
85
+ if shift["notes"].to_s == ""
86
+ str += "No notes\n"
87
+ else
88
+ str += "#{shift["notes"]}\n"
89
+ end
90
+ str += "\n"
91
+ end
92
+
93
+ overdue = @project["grand_total"] > @project["time_limit"] if @project["time_limit"]
94
+ if overdue
95
+ str += "Total: #{HighLine::String.new(to_clock_s(total)).red}"
96
+ else
97
+ str += "Total: #{to_clock_s(total)}"
98
+ end
99
+
100
+ say(str)
101
+ end
102
+
103
+ def log_table
104
+ buffer = ''
105
+ shifts = JSON.parse(@access_key.get("/api/1/projects/#{@project["uuid"]}/shifts.json").body)
106
+
107
+ company = @cache.companies(true)[@project["company_uuid"]]
108
+ staff = @cache.staff(true)
109
+ buffer += "#{company["name"]}: #{@project["name"]} shifts:\n\n"
110
+
111
+ total = 0
112
+ rows = []
113
+ shifts["response"].each do |shift|
114
+ row = []
115
+
116
+ staff_member = staff[shift["user_uuid"]]
117
+ start = Time.parse(shift["start"])
118
+ stop = Time.parse(shift["stop"] || Time.now.to_s)
119
+ total += (stop - start)
120
+
121
+ if staff_member
122
+ row << "#{staff_member["first_name"]} #{staff_member["last_name"]}"
123
+ else
124
+ row << "[Deleted user]"
125
+ end
126
+ row << "#{start.getlocal.strftime("%d/%M/%Y %H:%M:%S")} - #{stop.getlocal.strftime("%H:%M:%S")}"
127
+ row << "#{to_clock_s(stop - start)}"
128
+
129
+ if shift["notes"].to_s == ""
130
+ row << " No notes"
131
+ else
132
+ row << " #{shift["notes"]}"
133
+ end
134
+
135
+ if shift["stop"].nil?
136
+ row = row.map{ |col| HighLine::String.new(col).green }
137
+ end
138
+ rows << row
139
+ end
140
+
141
+ rows << :separator
142
+ overdue = @project["grand_total"] > @project["time_limit"] if @project["time_limit"]
143
+ if overdue
144
+ rows << [ 'Total', '', HighLine::String.new(to_clock_s(total)).red, '' ]
145
+ else
146
+ rows << [ 'Total', '', to_clock_s(total), '' ]
147
+ end
148
+
149
+ say(Terminal::Table.new(:rows => rows).to_s) if @options[:table]
150
+ end
151
+
152
+ def to_clock_s(time, show_seconds = false)
153
+ hour = (time.abs / 3600).floor
154
+ minute = (time.abs / 60 % 60).floor
155
+ seconds = (time.abs % 60).floor if show_seconds
156
+
157
+ return (time != 0 && (time / time.abs) == -1 ? "-" : "") + hour.to_s.rjust(2, '0') + ":" + minute.to_s.rjust(2, '0') + (show_seconds ? ":" + seconds.to_s.rjust(2, '0') : '')
158
+ end
159
+
160
+ end
161
+ end
162
+ end