fuzzy_time_ago 1.0.0
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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +16 -0
- data/Dockerfile +33 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +78 -0
- data/LICENSE.txt +21 -0
- data/README.md +107 -0
- data/Rakefile +17 -0
- data/Vagrantfile +65 -0
- data/fuzzy_time_ago.gemspec +30 -0
- data/fuzzy_time_ago.sublime-project +8 -0
- data/lib/fuzzy_time_ago/version.rb +5 -0
- data/lib/fuzzy_time_ago.rb +58 -0
- metadata +72 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: cbe2d9d7bd9fc1219b232362f7a650dc6ddcf505887a4b7f99d27313354a99d6
|
|
4
|
+
data.tar.gz: c4f890d09417ee589b2d902ad1eb13fea1b71e8a7e2b582392e8e7b7bc9149a0
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f48fcdebc6762ec7170eeb85e66cd69702fe50f18af336200843bf6adf9342a0078a279c69fe4c767537a8dd117dba5e67e4e5c2a5a6f580a4ecd24b6d4f2050
|
|
7
|
+
data.tar.gz: e93ba5f89d5bc0402dea16e952f198dceb292fa11311a3dcce1878aae069f116c582326fdb4835bfa6551fae312fae054b725fb54d22fc985445d725304a393c
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
plugins:
|
|
2
|
+
- rubocop-rspec
|
|
3
|
+
- rubocop-rake
|
|
4
|
+
|
|
5
|
+
# Disable metrics. Although fuzzy_ago is long, it is in reality not complex at all
|
|
6
|
+
Metrics:
|
|
7
|
+
Enabled: false
|
|
8
|
+
|
|
9
|
+
RSpec/MultipleExpectations:
|
|
10
|
+
Enabled: false
|
|
11
|
+
RSpec/ExampleLength:
|
|
12
|
+
Max: 10
|
|
13
|
+
|
|
14
|
+
AllCops:
|
|
15
|
+
Exclude:
|
|
16
|
+
- 'vendor/**/*'
|
data/Dockerfile
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# This image is (indirectly) based on the official ubuntu:jammy image, but includes git, curl, wget and some other stuff out of the box.
|
|
2
|
+
FROM buildpack-deps:jammy
|
|
3
|
+
|
|
4
|
+
ARG USERNAME=vagrant
|
|
5
|
+
ARG UID=1000
|
|
6
|
+
ARG GID=1000
|
|
7
|
+
ARG KEYFILE=
|
|
8
|
+
|
|
9
|
+
# Set up default user
|
|
10
|
+
RUN groupadd -g $GID $USERNAME
|
|
11
|
+
RUN useradd -m -u $UID -g $GID -s /bin/bash $USERNAME
|
|
12
|
+
|
|
13
|
+
# This system has been minimized by removing packages and content that are required on a system that users do not log into.
|
|
14
|
+
# unminimize restores content and packages that are found on a default server system in order to make this system more suitable for interactive use.
|
|
15
|
+
RUN yes | unminimize
|
|
16
|
+
|
|
17
|
+
# Install sudo (which for some bizarre reason is missing, and not restored by unminimize) and an SSH server.
|
|
18
|
+
RUN apt-get update && apt-get install -y sudo openssh-server
|
|
19
|
+
# Allow the default user passwordless sudo
|
|
20
|
+
RUN echo "$USERNAME ALL = NOPASSWD: ALL" >> /etc/sudoers
|
|
21
|
+
|
|
22
|
+
# Configure SSH access with the passed public key (KEYFILE)
|
|
23
|
+
RUN mkdir /var/run/sshd
|
|
24
|
+
RUN mkdir -p "/home/$USERNAME/.ssh"
|
|
25
|
+
COPY $KEYFILE "/home/$USERNAME/.ssh/authorized_keys"
|
|
26
|
+
RUN chown -R "$USERNAME":"$USERNAME" "/home/$USERNAME/.ssh"
|
|
27
|
+
RUN echo "Host remotehost\n\tStrictHostKeyChecking no\n" >> "/home/$USERNAME/.ssh/config"
|
|
28
|
+
|
|
29
|
+
# Open port for SSH
|
|
30
|
+
EXPOSE 22
|
|
31
|
+
|
|
32
|
+
# Run SSH server (daemonized)
|
|
33
|
+
CMD ["/usr/sbin/sshd", "-D"]
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
fuzzy_time_ago (1.0.0)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
ast (2.4.3)
|
|
10
|
+
bump (0.10.0)
|
|
11
|
+
diff-lcs (1.6.2)
|
|
12
|
+
json (2.14.1)
|
|
13
|
+
language_server-protocol (3.17.0.5)
|
|
14
|
+
lint_roller (1.1.0)
|
|
15
|
+
parallel (1.27.0)
|
|
16
|
+
parser (3.3.9.0)
|
|
17
|
+
ast (~> 2.4.1)
|
|
18
|
+
racc
|
|
19
|
+
prism (1.5.1)
|
|
20
|
+
racc (1.8.1)
|
|
21
|
+
rainbow (3.1.1)
|
|
22
|
+
rake (13.3.0)
|
|
23
|
+
regexp_parser (2.11.3)
|
|
24
|
+
rspec (3.13.1)
|
|
25
|
+
rspec-core (~> 3.13.0)
|
|
26
|
+
rspec-expectations (~> 3.13.0)
|
|
27
|
+
rspec-mocks (~> 3.13.0)
|
|
28
|
+
rspec-core (3.13.5)
|
|
29
|
+
rspec-support (~> 3.13.0)
|
|
30
|
+
rspec-expectations (3.13.5)
|
|
31
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
32
|
+
rspec-support (~> 3.13.0)
|
|
33
|
+
rspec-mocks (3.13.5)
|
|
34
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
35
|
+
rspec-support (~> 3.13.0)
|
|
36
|
+
rspec-support (3.13.6)
|
|
37
|
+
rubocop (1.80.2)
|
|
38
|
+
json (~> 2.3)
|
|
39
|
+
language_server-protocol (~> 3.17.0.2)
|
|
40
|
+
lint_roller (~> 1.1.0)
|
|
41
|
+
parallel (~> 1.10)
|
|
42
|
+
parser (>= 3.3.0.2)
|
|
43
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
44
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
45
|
+
rubocop-ast (>= 1.46.0, < 2.0)
|
|
46
|
+
ruby-progressbar (~> 1.7)
|
|
47
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
48
|
+
rubocop-ast (1.47.0)
|
|
49
|
+
parser (>= 3.3.7.2)
|
|
50
|
+
prism (~> 1.4)
|
|
51
|
+
rubocop-rake (0.7.1)
|
|
52
|
+
lint_roller (~> 1.1)
|
|
53
|
+
rubocop (>= 1.72.1)
|
|
54
|
+
rubocop-rspec (3.7.0)
|
|
55
|
+
lint_roller (~> 1.1)
|
|
56
|
+
rubocop (~> 1.72, >= 1.72.1)
|
|
57
|
+
ruby-progressbar (1.13.0)
|
|
58
|
+
timecop (0.9.10)
|
|
59
|
+
unicode-display_width (3.2.0)
|
|
60
|
+
unicode-emoji (~> 4.1)
|
|
61
|
+
unicode-emoji (4.1.0)
|
|
62
|
+
|
|
63
|
+
PLATFORMS
|
|
64
|
+
ruby
|
|
65
|
+
x86_64-linux
|
|
66
|
+
|
|
67
|
+
DEPENDENCIES
|
|
68
|
+
bump
|
|
69
|
+
fuzzy_time_ago!
|
|
70
|
+
rake
|
|
71
|
+
rspec
|
|
72
|
+
rubocop
|
|
73
|
+
rubocop-rake
|
|
74
|
+
rubocop-rspec
|
|
75
|
+
timecop
|
|
76
|
+
|
|
77
|
+
BUNDLED WITH
|
|
78
|
+
2.7.2
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 BadIdeaException
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# FuzzyTimeAgo
|
|
2
|
+
|
|
3
|
+
A Ruby gem that converts timestamps into fuzzy, human-friendly relative time strings like "less than a minute ago", "2 months ago", "over a year ago", etc. It is intended as a light-weight replacement to Rails' [`time-ago-in-words`](https://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html#method-i-time_ago_in_words), albeit not an exact replacement (see section [Differences](#differences))
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'fuzzy_time_ago'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
$ bundle install
|
|
16
|
+
|
|
17
|
+
Or install it yourself as:
|
|
18
|
+
|
|
19
|
+
$ gem install fuzzy_time_ago
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
require 'fuzzy_time_ago'
|
|
25
|
+
|
|
26
|
+
# Basic usage with Time or Date objects
|
|
27
|
+
FuzzyTimeAgo.fuzzy_ago(Time.now - 30) # => "less than a minute ago"
|
|
28
|
+
FuzzyTimeAgo.fuzzy_ago(Time.now - 3600) # => "about an hour ago"
|
|
29
|
+
FuzzyTimeAgo.fuzzy_ago(Date.today - 1) # => "a day ago"
|
|
30
|
+
|
|
31
|
+
# Convenience method on Time objects
|
|
32
|
+
Time.now.fuzzy_ago # => "less than a minute ago"
|
|
33
|
+
(Time.now - 86400).fuzzy_ago # => "a day ago"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Output Specification
|
|
37
|
+
|
|
38
|
+
| Time Range | Output Format |
|
|
39
|
+
|:-----------|:--------------|
|
|
40
|
+
| 0-59 seconds | `"less than a minute ago"` |
|
|
41
|
+
| 60-119 seconds | `"about a minute ago"` |
|
|
42
|
+
| 2-59 minutes | `"X minutes ago"` |
|
|
43
|
+
| 1-2 hours | `"about an hour ago"` |
|
|
44
|
+
| 2-23 hours | `"about X hours ago"` |
|
|
45
|
+
| 1 day | `"a day ago"` |
|
|
46
|
+
| 2-6 days | `"X days ago"` |
|
|
47
|
+
| 1 week | `"about a week ago"` |
|
|
48
|
+
| 2+ weeks | `"about X weeks ago"` |
|
|
49
|
+
| 1 month | `"about a month ago"` |
|
|
50
|
+
| 2 months | `"about 2 months ago"` |
|
|
51
|
+
| 3-11 months | `"X months ago"` |
|
|
52
|
+
| 12 months - 15 months | `"about a year ago"` |
|
|
53
|
+
| 15 months - 21 months | `"over a year ago"` |
|
|
54
|
+
| 21 months - 2 years | `"almost 2 years ago"` |
|
|
55
|
+
| 2+ years | "about/over/almost X years ago" |
|
|
56
|
+
|
|
57
|
+
*Note: For periods longer than weeks, the gem uses calendar-based calculations rather than fixed day counts.*
|
|
58
|
+
|
|
59
|
+
## Differences from Rails' `time_ago_in_words`
|
|
60
|
+
|
|
61
|
+
### Output Format Differences
|
|
62
|
+
|
|
63
|
+
| Time Period | FuzzyTimeAgo | Rails `time_ago_in_words` | Explanation |
|
|
64
|
+
|:------------|:-------------|:--------------------------|:------------|
|
|
65
|
+
| 1 day | `"a day"` | `"1 day"` | Uses "a" instead of "1" |
|
|
66
|
+
| 1 week | `"about a week"` | `"7 days"` | Switches unit to weeks, while Rails continues to use days |
|
|
67
|
+
| 1 month | `"about a month"` | `"about 1 month"` | Uses "a" instead of "1" |
|
|
68
|
+
| 1 year | `"about a year"` | `"about 1 year"` | Uses "a" instead of "1" |
|
|
69
|
+
|
|
70
|
+
### Calendar Arithmetic vs Fixed Duration
|
|
71
|
+
|
|
72
|
+
**The most significant difference is in how longer periods are calculated:**
|
|
73
|
+
|
|
74
|
+
- **FuzzyTimeAgo**: Uses true calendar arithmetic
|
|
75
|
+
- Calculates months by actual calendar months
|
|
76
|
+
- Adjusts for day-of-month differences
|
|
77
|
+
- Respects varying month lengths (28-31 days) and leap years
|
|
78
|
+
|
|
79
|
+
- **Rails**: Uses fixed duration approximations
|
|
80
|
+
- Assumes all months are 30 days
|
|
81
|
+
- Assumes all years are 365 days
|
|
82
|
+
- Only accounts for leap years in final year calculation, not month calculations
|
|
83
|
+
|
|
84
|
+
**Practical impact**: For periods longer than weeks, this gem will be more accurate for actual calendar dates, while Rails provides consistent duration-based approximations.
|
|
85
|
+
|
|
86
|
+
## Development
|
|
87
|
+
|
|
88
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake spec` to run the tests.
|
|
89
|
+
|
|
90
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
91
|
+
|
|
92
|
+
For version management, this gem uses [`bump`](https://github.com/gregorym/bump):
|
|
93
|
+
```
|
|
94
|
+
bundle exec rake bump:major
|
|
95
|
+
bundle exec rake bump:patch
|
|
96
|
+
bundle exec rake bump:minor
|
|
97
|
+
bundle exec rake bump:pre
|
|
98
|
+
```
|
|
99
|
+
Release and publishing are automated through a Github Actions workflow.
|
|
100
|
+
|
|
101
|
+
## Contributing
|
|
102
|
+
|
|
103
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/BadIdeaException/fuzzy_time_ago.
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
4
|
+
require 'rspec/core/rake_task'
|
|
5
|
+
require 'rubocop/rake_task'
|
|
6
|
+
require 'bump/tasks'
|
|
7
|
+
|
|
8
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
9
|
+
RuboCop::RakeTask.new(:lint)
|
|
10
|
+
|
|
11
|
+
desc 'Run the specs'
|
|
12
|
+
task default: :spec
|
|
13
|
+
|
|
14
|
+
Bump.tag_by_default = true
|
|
15
|
+
Rake::Task['bump:patch'].enhance(%w[lint spec])
|
|
16
|
+
Rake::Task['bump:minor'].enhance(%w[lint spec])
|
|
17
|
+
Rake::Task['bump:major'].enhance(%w[lint spec])
|
data/Vagrantfile
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# -*- mode: ruby -*-
|
|
4
|
+
# vi: set ft=ruby :
|
|
5
|
+
|
|
6
|
+
# All Vagrant configuration is done below. The "2" in Vagrant.configure
|
|
7
|
+
# configures the configuration version (we support older styles for
|
|
8
|
+
# backwards compatibility). Please don"t change it unless you know what
|
|
9
|
+
# you"re doing.
|
|
10
|
+
|
|
11
|
+
USERNAME = 'vagrant'
|
|
12
|
+
|
|
13
|
+
Vagrant.configure('2') do |config|
|
|
14
|
+
config.vm.provider 'docker' do |docker|
|
|
15
|
+
# Create ssh keys unless they are already created
|
|
16
|
+
`ssh-keygen -f #{USERNAME}.key -t ed25519 -N ""` unless File.file?("#{USERNAME}.key")
|
|
17
|
+
|
|
18
|
+
docker.build_dir = '.'
|
|
19
|
+
docker.build_args = [
|
|
20
|
+
# Make default user inside the VM have the same UID and GID as the user running the vagrant command
|
|
21
|
+
# This makes it a lot easier working with shared code locations, because the user will own the files
|
|
22
|
+
'--build-arg', "USERNAME=#{USERNAME}",
|
|
23
|
+
'--build-arg', "UID=#{Process.uid}",
|
|
24
|
+
'--build-arg', "GID=#{Process.gid}",
|
|
25
|
+
'--build-arg', "KEYFILE=#{USERNAME}.key.pub"
|
|
26
|
+
]
|
|
27
|
+
docker.has_ssh = true
|
|
28
|
+
docker.remains_running = true
|
|
29
|
+
# Use project"s directory name as name for the container.
|
|
30
|
+
# (Note that this will fail if such a container already exists.)
|
|
31
|
+
docker.name = File.dirname(__FILE__).split('/').last
|
|
32
|
+
# Use container name as hostname inside the container, as is the default behavior for other providers.
|
|
33
|
+
docker.create_args = ['--hostname', docker.name]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
config.ssh.username = USERNAME
|
|
37
|
+
config.ssh.private_key_path = "#{USERNAME}.key"
|
|
38
|
+
|
|
39
|
+
# Expose port 9229 to allow debugging
|
|
40
|
+
config.vm.network :forwarded_port, guest: 9229, host: 9229
|
|
41
|
+
|
|
42
|
+
config.vm.provision 'shell', name: 'Install Ruby', env: { 'RUBY_VERSION' => '3.4.5' }, inline: <<-SHELL
|
|
43
|
+
echo "Building Ruby v${RUBY_VERSION} from source."
|
|
44
|
+
curl -L https://cache.ruby-lang.org/pub/ruby/${RUBY_VERSION%.*}/ruby-${RUBY_VERSION}.tar.gz | tar -xz -C /tmp
|
|
45
|
+
cd "/tmp/ruby-${RUBY_VERSION}"
|
|
46
|
+
./configure
|
|
47
|
+
make
|
|
48
|
+
make install
|
|
49
|
+
SHELL
|
|
50
|
+
config.vm.provision 'shell', name: 'Install Bundler', privileged: false,
|
|
51
|
+
inline: "gem install bundler && bundle config set --local path '/vagrant/vendor/bundle'"
|
|
52
|
+
|
|
53
|
+
config.vm.provision 'shell', name: 'Install aider', privileged: false,
|
|
54
|
+
inline: <<-SHELL
|
|
55
|
+
sudo apt-get update && sudo apt-get install -y python3-pip
|
|
56
|
+
python3 -m pip install --user aider-install
|
|
57
|
+
/home/vagrant/.local/bin/aider-install
|
|
58
|
+
SHELL
|
|
59
|
+
|
|
60
|
+
config.vm.provision 'file', source: '~/.aider.conf.yml',
|
|
61
|
+
destination: '/home/vagrant/.aider.conf.yml'
|
|
62
|
+
|
|
63
|
+
config.ssh.extra_args = ['-t', 'cd /vagrant; bash --login']
|
|
64
|
+
end
|
|
65
|
+
# rubocop:enable Metrics
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/fuzzy_time_ago/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'fuzzy_time_ago'
|
|
7
|
+
spec.version = FuzzyTimeAgo::VERSION
|
|
8
|
+
spec.authors = ['BadIdeaException']
|
|
9
|
+
|
|
10
|
+
spec.summary = 'Create fuzzy, human-readable time ago strings'
|
|
11
|
+
spec.description = 'A Ruby gem that converts timestamps into fuzzy, human-friendly relative time strings ' \
|
|
12
|
+
"like 'less than a minute ago', 'about 2 months ago', etc."
|
|
13
|
+
spec.homepage = 'https://github.com/BadIdeaException/fuzzy_time_ago'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 2.7.0'
|
|
16
|
+
|
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/BadIdeaException/fuzzy_time_ago'
|
|
19
|
+
|
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
|
21
|
+
spec.files = Dir.chdir(__dir__) do
|
|
22
|
+
`git ls-files -z 2>/dev/null`.split("\x0").reject do |f|
|
|
23
|
+
f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
spec.require_paths = ['lib']
|
|
27
|
+
|
|
28
|
+
# Development dependencies
|
|
29
|
+
spec.add_development_dependency 'timecop'
|
|
30
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'fuzzy_time_ago/version'
|
|
4
|
+
|
|
5
|
+
# FuzzyTimeAgo provides a method to convert timestamps into fuzzy, human-readable
|
|
6
|
+
# descriptions of the time elapsed relative to the current system time.
|
|
7
|
+
module FuzzyTimeAgo
|
|
8
|
+
class Error < StandardError; end
|
|
9
|
+
Difference = Struct.new(:seconds, :minutes, :hours, :days, :weeks, :months, :years)
|
|
10
|
+
|
|
11
|
+
# Convert a timestamp into a fuzzy, human-readable string specifying the difference to current system time
|
|
12
|
+
def self.fuzzy_ago(target_time)
|
|
13
|
+
raise ArgumentError, 'Expected Time or Date object' unless target_time.is_a?(Time) || target_time.is_a?(Date)
|
|
14
|
+
|
|
15
|
+
target_time = target_time.to_time if target_time.is_a?(Date)
|
|
16
|
+
|
|
17
|
+
now = Time.now
|
|
18
|
+
delta = now.to_i - target_time.to_i
|
|
19
|
+
|
|
20
|
+
case delta
|
|
21
|
+
when 0...60 then return 'less than a minute ago'
|
|
22
|
+
when 60...120 then return 'about a minute ago'
|
|
23
|
+
when 120...3600 then return "#{(delta / 60).to_i} minutes ago"
|
|
24
|
+
when 3600...7200 then return 'about an hour ago'
|
|
25
|
+
when 7200...24 * 3600 then return "about #{(delta / 3600).to_i} hours ago"
|
|
26
|
+
when 24 * 3600...48 * 3600 then return 'a day ago'
|
|
27
|
+
when 48 * 3600...7 * 24 * 3600 then return "#{(delta / (24 * 3600)).to_i} days ago"
|
|
28
|
+
when 7 * 24 * 3600...14 * 24 * 3600 then return 'about a week ago'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
months_ago = (now.month - target_time.month) + 12 * (now.year - target_time.year)
|
|
32
|
+
months_ago -= 1 if now.day < target_time.day
|
|
33
|
+
# binding.break
|
|
34
|
+
case months_ago
|
|
35
|
+
when 0 then return "about #{(delta / (7 * 24 * 3600)).to_i} weeks ago"
|
|
36
|
+
when 1 then return 'about a month ago'
|
|
37
|
+
when 2 then return 'about 2 months ago'
|
|
38
|
+
when 3...12 then return "#{months_ago} months ago"
|
|
39
|
+
when 12...15 then return 'about a year ago'
|
|
40
|
+
when 15...21 then return 'over a year ago'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
years_ago = (months_ago / 12).to_i
|
|
44
|
+
months_ago %= 12
|
|
45
|
+
case months_ago
|
|
46
|
+
when 0...3 then "about #{years_ago} years ago"
|
|
47
|
+
when 3...9 then "over #{years_ago} years ago"
|
|
48
|
+
when 9...12 then "almost #{years_ago + 1} years ago"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Add convenience method to Time class
|
|
54
|
+
class Time
|
|
55
|
+
def fuzzy_ago
|
|
56
|
+
FuzzyTimeAgo.fuzzy_ago(self)
|
|
57
|
+
end
|
|
58
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fuzzy_time_ago
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- BadIdeaException
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-09-21 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: timecop
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
description: A Ruby gem that converts timestamps into fuzzy, human-friendly relative
|
|
28
|
+
time strings like 'less than a minute ago', 'about 2 months ago', etc.
|
|
29
|
+
email:
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- ".rspec"
|
|
35
|
+
- ".rubocop.yml"
|
|
36
|
+
- Dockerfile
|
|
37
|
+
- Gemfile
|
|
38
|
+
- Gemfile.lock
|
|
39
|
+
- LICENSE.txt
|
|
40
|
+
- README.md
|
|
41
|
+
- Rakefile
|
|
42
|
+
- Vagrantfile
|
|
43
|
+
- fuzzy_time_ago.gemspec
|
|
44
|
+
- fuzzy_time_ago.sublime-project
|
|
45
|
+
- lib/fuzzy_time_ago.rb
|
|
46
|
+
- lib/fuzzy_time_ago/version.rb
|
|
47
|
+
homepage: https://github.com/BadIdeaException/fuzzy_time_ago
|
|
48
|
+
licenses:
|
|
49
|
+
- MIT
|
|
50
|
+
metadata:
|
|
51
|
+
homepage_uri: https://github.com/BadIdeaException/fuzzy_time_ago
|
|
52
|
+
source_code_uri: https://github.com/BadIdeaException/fuzzy_time_ago
|
|
53
|
+
post_install_message:
|
|
54
|
+
rdoc_options: []
|
|
55
|
+
require_paths:
|
|
56
|
+
- lib
|
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 2.7.0
|
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - ">="
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '0'
|
|
67
|
+
requirements: []
|
|
68
|
+
rubygems_version: 3.4.19
|
|
69
|
+
signing_key:
|
|
70
|
+
specification_version: 4
|
|
71
|
+
summary: Create fuzzy, human-readable time ago strings
|
|
72
|
+
test_files: []
|