whenwords 0.1.0 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b632b8d1b88e484cd487236d6f074de258636bbc8485fe633c57f4d0da3a20a
4
- data.tar.gz: 2c3dd46ebccb057efd996a6c13c287f8a216509ae9037e46d19c37b0ee57026d
3
+ metadata.gz: 3bd67c93384599212636f8539189dec434b1c0e3c0fb78ecf9b31039df9560f4
4
+ data.tar.gz: 577b977de38168eb4863dad6384ed0ffdcfe03a3cc0becee46ac9c61092161c7
5
5
  SHA512:
6
- metadata.gz: f4c62f91e2837875c537c3b2f3fc51fb7f9a7c2855da99e4cd41fd61f4ca6392166da376ddd0b3294a18a39b856fa7cfb6a7ec95f6eb3d520422ce5b7f91cac6
7
- data.tar.gz: ff07da6df5d2cc3d719019cf309916ac29627c3f974058bf12ea9bdb29de8be6ae4a945ea35111dfa4694b06bcdc7661e8a2006209e958e243fd05b673a8be36
6
+ metadata.gz: 150a6aea8bd49cbb182e405ad8d6a2e2bdab29087b4a207d2865ddc9e9447b5babfe45342cc61dcf1390089b7232f8077e4678e460aadefa657b44f16808dde1
7
+ data.tar.gz: fd1481665e27708fc22e4f86c781d7cc2b22193e40fe5c5680871182e214cddbe133645c68a5cdde34d97a79f7b31ea95d68bcb7c1a8f49527d6f8772a685bb4
data/README.md CHANGED
@@ -275,7 +275,11 @@ To install this gem onto your local machine, run `bundle exec rake install`.
275
275
 
276
276
  ## Contributing
277
277
 
278
- Bug reports and pull requests are welcome on GitHub at https://github.com/dbreunig/whenwords.
278
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ZPVIP/whenwords.
279
+
280
+ ## Credits
281
+
282
+ This Ruby gem is an implementation of the [whenwords specification](https://github.com/dbreunig/whenwords) by Drew Breunig — "An Open Source Library Without Code".
279
283
 
280
284
  ## License
281
285
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Whenwords
4
- VERSION = "0.1.0"
4
+ VERSION = '0.1.1'
5
5
  end
data/lib/whenwords.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "time"
4
- require_relative "whenwords/version"
3
+ require 'time'
4
+ require_relative 'whenwords/version'
5
5
 
6
6
  module Whenwords
7
7
  class Error < StandardError; end
@@ -9,10 +9,10 @@ module Whenwords
9
9
 
10
10
  SECONDS_PER_MINUTE = 60
11
11
  SECONDS_PER_HOUR = 3600
12
- SECONDS_PER_DAY = 86400
13
- SECONDS_PER_WEEK = 604800
14
- SECONDS_PER_MONTH = 2592000 # 30 days
15
- SECONDS_PER_YEAR = 31536000 # 365 days
12
+ SECONDS_PER_DAY = 86_400
13
+ SECONDS_PER_WEEK = 604_800
14
+ SECONDS_PER_MONTH = 2_592_000 # 30 days
15
+ SECONDS_PER_YEAR = 31_536_000 # 365 days
16
16
 
17
17
  WEEKDAY_NAMES = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday].freeze
18
18
  MONTH_NAMES = %w[January February March April May June July August September October November December].freeze
@@ -45,12 +45,12 @@ module Whenwords
45
45
  ref = reference.nil? ? ts : normalize_timestamp(reference)
46
46
 
47
47
  diff = ref - ts
48
- future = diff < 0
48
+ future = diff.negative?
49
49
  diff = diff.abs
50
50
 
51
51
  text = calculate_timeago_text(diff)
52
52
 
53
- if text == "just now"
53
+ if text == 'just now'
54
54
  text
55
55
  elsif future
56
56
  "in #{text.sub(/ ago$/, '')}"
@@ -65,13 +65,13 @@ module Whenwords
65
65
  # @param max_units [Integer] Maximum number of units to display
66
66
  # @return [String] Human-readable duration
67
67
  def duration(seconds, compact: false, max_units: 2)
68
- raise Error, "Duration cannot be negative" if seconds.negative?
69
- raise Error, "Duration cannot be NaN" if seconds.respond_to?(:nan?) && seconds.nan?
70
- raise Error, "Duration cannot be infinite" if seconds.respond_to?(:infinite?) && seconds.infinite?
68
+ raise Error, 'Duration cannot be negative' if seconds.negative?
69
+ raise Error, 'Duration cannot be NaN' if seconds.respond_to?(:nan?) && seconds.nan?
70
+ raise Error, 'Duration cannot be infinite' if seconds.respond_to?(:infinite?) && seconds.infinite?
71
71
 
72
72
  seconds = seconds.to_f
73
73
 
74
- return compact ? "0s" : "0 seconds" if seconds.zero?
74
+ return compact ? '0s' : '0 seconds' if seconds.zero?
75
75
 
76
76
  units = calculate_duration_units(seconds)
77
77
  non_zero_units = units.select { |_, v| v.positive? }
@@ -90,20 +90,18 @@ module Whenwords
90
90
  # @param string [String] The duration string to parse
91
91
  # @return [Numeric] Duration in seconds
92
92
  def parse_duration(string)
93
- raise ParseError, "Duration string cannot be empty" if string.nil? || string.strip.empty?
93
+ raise ParseError, 'Duration string cannot be empty' if string.nil? || string.strip.empty?
94
94
 
95
95
  input = string.strip.downcase
96
96
 
97
97
  # Check for negative values
98
- raise ParseError, "Negative durations are not allowed" if input.include?("-")
98
+ raise ParseError, 'Negative durations are not allowed' if input.include?('-')
99
99
 
100
100
  # Try colon notation first
101
- if input.match?(/^\d+:\d{1,2}(:\d{1,2})?$/)
102
- return parse_colon_notation(input)
103
- end
101
+ return parse_colon_notation(input) if input.match?(/^\d+:\d{1,2}(:\d{1,2})?$/)
104
102
 
105
103
  total = parse_duration_parts(input)
106
- raise ParseError, "No parseable duration units found" if total.zero? && !input.match?(/\b0\s*[a-z]/)
104
+ raise ParseError, 'No parseable duration units found' if total.zero? && !input.match?(/\b0\s*[a-z]/)
107
105
 
108
106
  total
109
107
  end
@@ -123,11 +121,11 @@ module Whenwords
123
121
 
124
122
  case diff_days
125
123
  when 0
126
- "Today"
124
+ 'Today'
127
125
  when -1
128
- "Yesterday"
126
+ 'Yesterday'
129
127
  when 1
130
- "Tomorrow"
128
+ 'Tomorrow'
131
129
  when -6..-2
132
130
  "Last #{WEEKDAY_NAMES[ts_date.wday]}"
133
131
  when 2..6
@@ -159,27 +157,27 @@ module Whenwords
159
157
  def calculate_timeago_text(diff)
160
158
  case diff
161
159
  when 0...45
162
- "just now"
160
+ 'just now'
163
161
  when 45...90
164
- "1 minute ago"
162
+ '1 minute ago'
165
163
  when 90...(45 * 60)
166
164
  "#{(diff / 60.0).round} minutes ago"
167
165
  when (45 * 60)...(90 * 60)
168
- "1 hour ago"
166
+ '1 hour ago'
169
167
  when (90 * 60)...(22 * 3600)
170
168
  "#{(diff / 3600.0).round} hours ago"
171
169
  when (22 * 3600)...(36 * 3600)
172
- "1 day ago"
173
- when (36 * 3600)...(26 * 86400)
174
- "#{(diff / 86400.0).round} days ago"
175
- when (26 * 86400)...(46 * 86400)
176
- "1 month ago"
177
- when (46 * 86400)...(320 * 86400)
178
- "#{(diff / (30.44 * 86400)).round} months ago"
179
- when (320 * 86400)...(548 * 86400)
180
- "1 year ago"
170
+ '1 day ago'
171
+ when (36 * 3600)...(26 * 86_400)
172
+ "#{(diff / 86_400.0).round} days ago"
173
+ when (26 * 86_400)...(46 * 86_400)
174
+ '1 month ago'
175
+ when (46 * 86_400)...(320 * 86_400)
176
+ "#{(diff / (30.44 * 86_400)).round} months ago"
177
+ when (320 * 86_400)...(548 * 86_400)
178
+ '1 year ago'
181
179
  else
182
- "#{(diff / (365.0 * 86400)).round} years ago"
180
+ "#{(diff / (365.0 * 86_400)).round} years ago"
183
181
  end
184
182
  end
185
183
 
@@ -213,34 +211,34 @@ module Whenwords
213
211
 
214
212
  def format_compact_duration(units)
215
213
  abbreviations = {
216
- years: "y",
217
- months: "mo",
218
- days: "d",
219
- hours: "h",
220
- minutes: "m",
221
- seconds: "s"
214
+ years: 'y',
215
+ months: 'mo',
216
+ days: 'd',
217
+ hours: 'h',
218
+ minutes: 'm',
219
+ seconds: 's'
222
220
  }
223
221
 
224
- units.map { |unit, value| "#{value}#{abbreviations[unit]}" }.join(" ")
222
+ units.map { |unit, value| "#{value}#{abbreviations[unit]}" }.join(' ')
225
223
  end
226
224
 
227
225
  def format_verbose_duration(units)
228
226
  units.map do |unit, value|
229
227
  unit_name = unit.to_s
230
- unit_name = unit_name.chomp("s") if value == 1
228
+ unit_name = unit_name.chomp('s') if value == 1
231
229
  "#{value} #{unit_name}"
232
- end.join(", ")
230
+ end.join(', ')
233
231
  end
234
232
 
235
233
  def parse_colon_notation(input)
236
- parts = input.split(":").map(&:to_i)
234
+ parts = input.split(':').map(&:to_i)
237
235
 
238
236
  if parts.length == 2
239
237
  # h:mm
240
- parts[0] * SECONDS_PER_HOUR + parts[1] * SECONDS_PER_MINUTE
238
+ (parts[0] * SECONDS_PER_HOUR) + (parts[1] * SECONDS_PER_MINUTE)
241
239
  else
242
240
  # h:mm:ss
243
- parts[0] * SECONDS_PER_HOUR + parts[1] * SECONDS_PER_MINUTE + parts[2]
241
+ (parts[0] * SECONDS_PER_HOUR) + (parts[1] * SECONDS_PER_MINUTE) + parts[2]
244
242
  end
245
243
  end
246
244
 
@@ -263,7 +261,7 @@ module Whenwords
263
261
  end
264
262
  end
265
263
 
266
- raise ParseError, "No parseable duration units found" unless found_any
264
+ raise ParseError, 'No parseable duration units found' unless found_any
267
265
 
268
266
  total.round
269
267
  end
@@ -277,14 +275,18 @@ module Whenwords
277
275
  end
278
276
 
279
277
  def format_date_range(start_date, end_date)
278
+ start_month = MONTH_NAMES[start_date.month - 1]
279
+ end_month = MONTH_NAMES[end_date.month - 1]
280
+
280
281
  if start_date == end_date
281
- "#{MONTH_NAMES[start_date.month - 1]} #{start_date.day}, #{start_date.year}"
282
+ "#{start_month} #{start_date.day}, #{start_date.year}"
282
283
  elsif start_date.year == end_date.year && start_date.month == end_date.month
283
- "#{MONTH_NAMES[start_date.month - 1]} #{start_date.day}–#{end_date.day}, #{start_date.year}"
284
+ "#{start_month} #{start_date.day}–#{end_date.day}, #{start_date.year}"
284
285
  elsif start_date.year == end_date.year
285
- "#{MONTH_NAMES[start_date.month - 1]} #{start_date.day} – #{MONTH_NAMES[end_date.month - 1]} #{end_date.day}, #{end_date.year}"
286
+ "#{start_month} #{start_date.day} – #{end_month} #{end_date.day}, #{end_date.year}"
286
287
  else
287
- "#{MONTH_NAMES[start_date.month - 1]} #{start_date.day}, #{start_date.year} – #{MONTH_NAMES[end_date.month - 1]} #{end_date.day}, #{end_date.year}"
288
+ "#{start_month} #{start_date.day}, #{start_date.year} – " \
289
+ "#{end_month} #{end_date.day}, #{end_date.year}"
288
290
  end
289
291
  end
290
292
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: whenwords
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
- - Drew Breunig
7
+ - Peng Zhang
8
8
  bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
@@ -13,7 +13,7 @@ description: Convert timestamps to readable strings like '3 hours ago' and parse
13
13
  strings like '2h 30m' into seconds. Includes timeago, duration formatting, duration
14
14
  parsing, contextual dates, and date range formatting.
15
15
  email:
16
- - drew@breunig.com
16
+ - peng@zpvip.com
17
17
  executables:
18
18
  - whenwords
19
19
  extensions: []
@@ -24,14 +24,14 @@ files:
24
24
  - exe/whenwords
25
25
  - lib/whenwords.rb
26
26
  - lib/whenwords/version.rb
27
- homepage: https://github.com/dbreunig/whenwords
27
+ homepage: https://github.com/ZPVIP/whenwords
28
28
  licenses:
29
29
  - MIT
30
30
  metadata:
31
- homepage_uri: https://github.com/dbreunig/whenwords
32
- source_code_uri: https://github.com/dbreunig/whenwords
33
- changelog_uri: https://github.com/dbreunig/whenwords/blob/main/CHANGELOG.md
34
- documentation_uri: https://github.com/dbreunig/whenwords#readme
31
+ homepage_uri: https://github.com/ZPVIP/whenwords
32
+ source_code_uri: https://github.com/ZPVIP/whenwords.git
33
+ changelog_uri: https://github.com/ZPVIP/whenwords/blob/main/CHANGELOG.md
34
+ documentation_uri: https://github.com/ZPVIP/whenwords#readme
35
35
  rubygems_mfa_required: 'true'
36
36
  rdoc_options: []
37
37
  require_paths: