date_breakup 2.0.0 → 3.1.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 +4 -4
- data/.claude/settings.json +23 -0
- data/.github/workflows/ci.yml +16 -0
- data/.gitignore +5 -1
- data/.mise.toml +2 -0
- data/.rubocop.yml +29 -0
- data/CHANGELOG.md +44 -0
- data/CLAUDE.md +39 -0
- data/Gemfile +4 -2
- data/Gemfile.lock +74 -0
- data/README.md +118 -49
- data/Rakefile +5 -3
- data/bin/console +5 -11
- data/date_breakup.gemspec +22 -21
- data/lib/date_breakup.rb +53 -170
- metadata +36 -27
- data/.travis.yml +0 -5
- data/lib/date_breakup/version.rb +0 -3
- data/lib/date_breakup_v1.rb +0 -215
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b0b112a6229d63cd8d490c5309d553c488533a819b09874b8f8019bf1c60f867
|
|
4
|
+
data.tar.gz: 57286315af767547d74f7efa1d346fbfb4785593a3d3eb47e7a35ebc2f7ccd8d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f9d67f0444647971676cbfb76d2bce7ac11d4fd1dea4516d330bcf415a7b4384a94db13beb83571321947979c62ff349f21a283610f4dbf22ff530a78abbf0f1
|
|
7
|
+
data.tar.gz: 2124f3c66ce6f2bbdbe8bf4cb27554f9c9af746e78403c3c14fa45b23533ee398d3fd762adff3bd3fa8aeff94c1058bfdea193719b48e748408fd6d97007a132
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"PostToolUse": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "Edit|Write",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "cd \"$(git rev-parse --show-toplevel)\" && file=$(jq -r '.tool_input.file_path // \"\"') && if echo \"$file\" | grep -qE '\\.rb$'; then bundle exec rubocop \"$file\" --format simple --no-color 2>/dev/null; fi",
|
|
10
|
+
"timeout": 30,
|
|
11
|
+
"statusMessage": "Running RuboCop..."
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"type": "command",
|
|
15
|
+
"command": "cd \"$(git rev-parse --show-toplevel)\" && bundle exec rspec --format progress --no-color 2>/dev/null",
|
|
16
|
+
"timeout": 60,
|
|
17
|
+
"statusMessage": "Running tests..."
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
jobs:
|
|
4
|
+
test:
|
|
5
|
+
runs-on: ubuntu-latest
|
|
6
|
+
strategy:
|
|
7
|
+
matrix:
|
|
8
|
+
ruby: ['3.3']
|
|
9
|
+
steps:
|
|
10
|
+
- uses: actions/checkout@v4
|
|
11
|
+
- uses: ruby/setup-ruby@v1
|
|
12
|
+
with:
|
|
13
|
+
ruby-version: ${{ matrix.ruby }}
|
|
14
|
+
bundler-cache: true
|
|
15
|
+
- run: bundle exec rspec
|
|
16
|
+
- run: bundle exec rubocop
|
data/.gitignore
CHANGED
data/.mise.toml
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
NewCops: disable
|
|
3
|
+
TargetRubyVersion: 3.3
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
|
|
6
|
+
Style/Documentation:
|
|
7
|
+
Enabled: false
|
|
8
|
+
|
|
9
|
+
Metrics/MethodLength:
|
|
10
|
+
Max: 30
|
|
11
|
+
|
|
12
|
+
Metrics/AbcSize:
|
|
13
|
+
Max: 40
|
|
14
|
+
|
|
15
|
+
Metrics/CyclomaticComplexity:
|
|
16
|
+
Max: 12
|
|
17
|
+
|
|
18
|
+
Metrics/PerceivedComplexity:
|
|
19
|
+
Max: 13
|
|
20
|
+
|
|
21
|
+
Metrics/BlockLength:
|
|
22
|
+
Exclude:
|
|
23
|
+
- 'spec/**/*'
|
|
24
|
+
- '*.gemspec'
|
|
25
|
+
|
|
26
|
+
Layout/LineLength:
|
|
27
|
+
Max: 120
|
|
28
|
+
Exclude:
|
|
29
|
+
- 'spec/**/*'
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [3.1.0] - 2026-05-10
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `.between` now accepts `Date` and `Time` objects in addition to date strings.
|
|
12
|
+
- `ArgumentError` raised when `start_date` is after `end_date` (previously returned silently empty results).
|
|
13
|
+
- GitHub Actions CI replacing Travis CI.
|
|
14
|
+
- `.mise.toml` to pin Ruby version for consistent local development.
|
|
15
|
+
- RuboCop added as a development dependency with a project `.rubocop.yml`.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Replaced `define_method` metaprogramming loop with four explicit public methods (`in_years`, `in_months`, `in_weeks`, `in_days`) backed by a shared private `build_breakdown` method. No change to public API behaviour.
|
|
19
|
+
- All result arrays are now method-local variables — calling any `in_*` method twice on the same instance no longer returns duplicated data.
|
|
20
|
+
- `frozen_string_literal: true` added to all Ruby files.
|
|
21
|
+
- Bundler constraint relaxed from `~> 2.2` to `~> 2.0`.
|
|
22
|
+
|
|
23
|
+
### Removed
|
|
24
|
+
- Runtime dependency on `time_difference` and implicit dependency on ActiveSupport — replaced with pure stdlib `Date` arithmetic. The gem now has zero runtime dependencies.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- `bundle install` previously failed because `time_difference` was required in `lib/date_breakup.rb` but never declared as a dependency.
|
|
28
|
+
|
|
29
|
+
## [3.0.1] - 2021-10-01
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- Dependency bump: `date` gem updated to `3.2.1`.
|
|
33
|
+
|
|
34
|
+
## [3.0.0] - 2021-09-01
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
- Class renamed from `DateBreakup::Range` to `DateBreakup`.
|
|
38
|
+
- Methods renamed: `get_years` → `in_years`, `get_months` → `in_months`, `get_weeks` → `in_weeks`, `get_days` → `in_days`.
|
|
39
|
+
- Internal code generation made dynamic via `define_method`.
|
|
40
|
+
|
|
41
|
+
## [1.0.0] - 2019-01-01
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
- Initial release. `DateBreakup::Range.between` with `get_years`, `get_months`, `get_weeks`, `get_days`.
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install dependencies
|
|
9
|
+
bin/setup
|
|
10
|
+
|
|
11
|
+
# Run all tests
|
|
12
|
+
bundle exec rake spec
|
|
13
|
+
# or
|
|
14
|
+
bundle exec rspec
|
|
15
|
+
|
|
16
|
+
# Run a single spec file
|
|
17
|
+
bundle exec rspec spec/date_breakup_spec.rb
|
|
18
|
+
|
|
19
|
+
# Interactive console (loads the gem)
|
|
20
|
+
bin/console
|
|
21
|
+
|
|
22
|
+
# Install gem locally
|
|
23
|
+
bundle exec rake install
|
|
24
|
+
|
|
25
|
+
# Release gem (bumps version tag, pushes to RubyGems)
|
|
26
|
+
bundle exec rake release
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Architecture
|
|
30
|
+
|
|
31
|
+
This is a single-file Ruby gem (`lib/date_breakup.rb`). The entire logic lives in the `DateBreakup` class.
|
|
32
|
+
|
|
33
|
+
**Entry point:** `DateBreakup.between(start_date, end_date)` — accepts `Date`, `Time`, or date strings; returns a `DateBreakup` instance. Raises `ArgumentError` if start is after end.
|
|
34
|
+
|
|
35
|
+
**Core pattern:** The four public methods (`in_years`, `in_months`, `in_weeks`, `in_days`) are all generated dynamically via `define_method` in a single `%w[years months weeks days].each` loop. Each method walks day-by-day from `@start_date` to `@end_date`, greedily consuming the largest possible unit (year > month > week > day) at each step. The `unit` variable in the loop controls which units are eligible — `in_days` only ever appends to `days`; `in_weeks` can use weeks and days; `in_months` can use months, weeks, and days; `in_years` can use all four.
|
|
36
|
+
|
|
37
|
+
**Return shape:** All four methods return the same hash `{ years: [], months: [], weeks: [], days: [] }` — higher-granularity methods simply leave the coarser arrays empty.
|
|
38
|
+
|
|
39
|
+
**Dependencies:** Zero runtime dependencies — uses only stdlib `require 'date'`.
|
data/Gemfile
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
source 'https://rubygems.org'
|
|
4
|
+
|
|
5
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
4
6
|
|
|
5
7
|
# Specify your gem's dependencies in date_breakup.gemspec
|
|
6
8
|
gemspec
|
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
date_breakup (3.1.0)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
ast (2.4.3)
|
|
10
|
+
coderay (1.1.3)
|
|
11
|
+
diff-lcs (1.4.4)
|
|
12
|
+
json (2.19.5)
|
|
13
|
+
language_server-protocol (3.17.0.5)
|
|
14
|
+
lint_roller (1.1.0)
|
|
15
|
+
method_source (1.0.0)
|
|
16
|
+
parallel (2.1.0)
|
|
17
|
+
parser (3.3.11.1)
|
|
18
|
+
ast (~> 2.4.1)
|
|
19
|
+
racc
|
|
20
|
+
prism (1.9.0)
|
|
21
|
+
pry (0.14.1)
|
|
22
|
+
coderay (~> 1.1)
|
|
23
|
+
method_source (~> 1.0)
|
|
24
|
+
racc (1.8.1)
|
|
25
|
+
rainbow (3.1.1)
|
|
26
|
+
rake (13.0.3)
|
|
27
|
+
regexp_parser (2.12.0)
|
|
28
|
+
rspec (3.10.0)
|
|
29
|
+
rspec-core (~> 3.10.0)
|
|
30
|
+
rspec-expectations (~> 3.10.0)
|
|
31
|
+
rspec-mocks (~> 3.10.0)
|
|
32
|
+
rspec-core (3.10.1)
|
|
33
|
+
rspec-support (~> 3.10.0)
|
|
34
|
+
rspec-expectations (3.10.1)
|
|
35
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
36
|
+
rspec-support (~> 3.10.0)
|
|
37
|
+
rspec-mocks (3.10.2)
|
|
38
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
39
|
+
rspec-support (~> 3.10.0)
|
|
40
|
+
rspec-support (3.10.2)
|
|
41
|
+
rubocop (1.86.1)
|
|
42
|
+
json (~> 2.3)
|
|
43
|
+
language_server-protocol (~> 3.17.0.2)
|
|
44
|
+
lint_roller (~> 1.1.0)
|
|
45
|
+
parallel (>= 1.10)
|
|
46
|
+
parser (>= 3.3.0.2)
|
|
47
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
48
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
49
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
50
|
+
ruby-progressbar (~> 1.7)
|
|
51
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
52
|
+
rubocop-ast (1.49.1)
|
|
53
|
+
parser (>= 3.3.7.2)
|
|
54
|
+
prism (~> 1.7)
|
|
55
|
+
ruby-progressbar (1.13.0)
|
|
56
|
+
unicode-display_width (3.2.0)
|
|
57
|
+
unicode-emoji (~> 4.1)
|
|
58
|
+
unicode-emoji (4.2.0)
|
|
59
|
+
|
|
60
|
+
PLATFORMS
|
|
61
|
+
arm64-darwin-23
|
|
62
|
+
x86_64-darwin-20
|
|
63
|
+
x86_64-linux
|
|
64
|
+
|
|
65
|
+
DEPENDENCIES
|
|
66
|
+
bundler (~> 2.0)
|
|
67
|
+
date_breakup!
|
|
68
|
+
pry (~> 0.14.1)
|
|
69
|
+
rake (~> 13.0, >= 13.0.3)
|
|
70
|
+
rspec (~> 3.10)
|
|
71
|
+
rubocop (~> 1.65)
|
|
72
|
+
|
|
73
|
+
BUNDLED WITH
|
|
74
|
+
2.7.2
|
data/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# DateBreakup
|
|
2
2
|
|
|
3
|
+
Pass two dates and get a breakdown of the range grouped into years, months, weeks, and days. Accepts `Date`, `Time`, or date strings.
|
|
4
|
+
|
|
3
5
|
## Installation
|
|
4
6
|
|
|
5
7
|
Add this line to your application's Gemfile:
|
|
@@ -8,74 +10,141 @@ Add this line to your application's Gemfile:
|
|
|
8
10
|
gem 'date_breakup'
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
Then run:
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
```sh
|
|
16
|
+
bundle install
|
|
17
|
+
```
|
|
14
18
|
|
|
15
|
-
Or install
|
|
19
|
+
Or install directly:
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
```sh
|
|
22
|
+
gem install date_breakup
|
|
23
|
+
```
|
|
18
24
|
|
|
19
25
|
## Usage
|
|
20
26
|
|
|
21
|
-
|
|
27
|
+
All four methods return the same hash shape — `{ years:, months:, weeks:, days: }` — with coarser arrays left empty depending on the method used.
|
|
28
|
+
|
|
29
|
+
`.between` accepts `Date`, `Time`, or a date string:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
DateBreakup.between(Date.new(2019, 1, 1), Date.new(2019, 12, 31))
|
|
33
|
+
DateBreakup.between(Time.new(2019, 1, 1), Time.new(2019, 12, 31))
|
|
34
|
+
DateBreakup.between('01/01/2019', '31/12/2019')
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Passing a start date after the end date raises `ArgumentError`.
|
|
38
|
+
|
|
39
|
+
### `in_years` — greedy breakdown from years down
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
DateBreakup.between('01/01/2019', '31/12/2019').in_years
|
|
43
|
+
# => {
|
|
44
|
+
# years: [{ year: 2019, start_date: Sat 01 Jan 2019, end_date: Sat 31 Dec 2019 }],
|
|
45
|
+
# months: [],
|
|
46
|
+
# weeks: [],
|
|
47
|
+
# days: []
|
|
48
|
+
# }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
For a range that doesn't align to full years, the remainder falls through to months, weeks, and days:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
DateBreakup.between('10/10/2010', '12/12/2012').in_years
|
|
55
|
+
# => {
|
|
56
|
+
# years: [{ year: 2011, start_date: Sat 01 Jan 2011, end_date: Sat 31 Dec 2011 }],
|
|
57
|
+
# months: [
|
|
58
|
+
# { month: 11, year: 2010, start_date: Mon 01 Nov 2010, end_date: Tue 30 Nov 2010 },
|
|
59
|
+
# { month: 12, year: 2010, start_date: Wed 01 Dec 2010, end_date: Fri 31 Dec 2010 },
|
|
60
|
+
# ...
|
|
61
|
+
# ],
|
|
62
|
+
# weeks: [{ week: 41, month: 10, year: 2010, start_date: Mon 11 Oct 2010, end_date: Sun 17 Oct 2010 }, ...],
|
|
63
|
+
# days: [{ day: 283, month_day: 10, month: 10, year: 2010, start_date: Sun 10 Oct 2010, end_date: Sun 10 Oct 2010 }, ...]
|
|
64
|
+
# }
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### `in_months` — greedy breakdown from months down
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
DateBreakup.between('01/01/2019', '31/12/2019').in_months
|
|
71
|
+
# => {
|
|
72
|
+
# years: [],
|
|
73
|
+
# months: [
|
|
74
|
+
# { month: 1, year: 2019, start_date: Tue 01 Jan 2019, end_date: Thu 31 Jan 2019 },
|
|
75
|
+
# { month: 2, year: 2019, start_date: Fri 01 Feb 2019, end_date: Thu 28 Feb 2019 },
|
|
76
|
+
# ...
|
|
77
|
+
# { month: 12, year: 2019, start_date: Sun 01 Dec 2019, end_date: Tue 31 Dec 2019 }
|
|
78
|
+
# ],
|
|
79
|
+
# weeks: [],
|
|
80
|
+
# days: []
|
|
81
|
+
# }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### `in_weeks` — greedy breakdown from weeks down
|
|
85
|
+
|
|
86
|
+
Partial weeks at the start or end of the range fall through to individual days.
|
|
22
87
|
|
|
23
88
|
```ruby
|
|
24
|
-
DateBreakup
|
|
25
|
-
=> {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
89
|
+
DateBreakup.between('01/01/2019', '31/12/2019').in_weeks
|
|
90
|
+
# => {
|
|
91
|
+
# years: [],
|
|
92
|
+
# months: [],
|
|
93
|
+
# weeks: [
|
|
94
|
+
# { week: 2, month: 1, year: 2019, start_date: Mon 07 Jan 2019, end_date: Sun 13 Jan 2019 },
|
|
95
|
+
# ...
|
|
96
|
+
# { week: 52, month: 12, year: 2019, start_date: Mon 23 Dec 2019, end_date: Sun 29 Dec 2019 }
|
|
97
|
+
# ],
|
|
98
|
+
# days: [
|
|
99
|
+
# { day: 1, month_day: 1, month: 1, year: 2019, start_date: Tue 01 Jan 2019, end_date: Tue 01 Jan 2019 },
|
|
100
|
+
# ...
|
|
101
|
+
# ]
|
|
102
|
+
# }
|
|
30
103
|
```
|
|
31
104
|
|
|
32
|
-
###
|
|
105
|
+
### `in_days` — every day individually
|
|
33
106
|
|
|
34
107
|
```ruby
|
|
35
|
-
DateBreakup
|
|
36
|
-
=> {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
{:month=>4, :year=>2012, :start_date=>Sun, 01 Apr 2012, :end_date=>Mon, 30 Apr 2012},
|
|
47
|
-
{:month=>5, :year=>2012, :start_date=>Tue, 01 May 2012, :end_date=>Thu, 31 May 2012},
|
|
48
|
-
{:month=>6, :year=>2012, :start_date=>Fri, 01 Jun 2012, :end_date=>Sat, 30 Jun 2012},
|
|
49
|
-
{:month=>7, :year=>2012, :start_date=>Sun, 01 Jul 2012, :end_date=>Tue, 31 Jul 2012},
|
|
50
|
-
{:month=>8, :year=>2012, :start_date=>Wed, 01 Aug 2012, :end_date=>Fri, 31 Aug 2012},
|
|
51
|
-
{:month=>9, :year=>2012, :start_date=>Sat, 01 Sep 2012, :end_date=>Sun, 30 Sep 2012},
|
|
52
|
-
{:month=>10, :year=>2012, :start_date=>Mon, 01 Oct 2012, :end_date=>Wed, 31 Oct 2012},
|
|
53
|
-
{:month=>11, :year=>2012, :start_date=>Thu, 01 Nov 2012, :end_date=>Fri, 30 Nov 2012}],
|
|
54
|
-
:weeks=>[
|
|
55
|
-
{:week=>41, :month=>10, :year=>2010, :start_date=>Mon, 11 Oct 2010, :end_date=>Sun, 17 Oct 2010},
|
|
56
|
-
{:week=>42, :month=>10, :year=>2010, :start_date=>Mon, 18 Oct 2010, :end_date=>Sun, 24 Oct 2010},
|
|
57
|
-
{:week=>43, :month=>10, :year=>2010, :start_date=>Mon, 25 Oct 2010, :end_date=>Sun, 31 Oct 2010},
|
|
58
|
-
{:week=>49, :month=>12, :year=>2012, :start_date=>Mon, 03 Dec 2012, :end_date=>Sun, 09 Dec 2012}],
|
|
59
|
-
:days=>[
|
|
60
|
-
{:day=>283, :month_day=>10, :month=>10, :year=>2010, :start_date=>Sun, 10 Oct 2010, :end_date=>Sun, 10 Oct 2010},
|
|
61
|
-
{:day=>336, :month_day=>1, :month=>12, :year=>2012, :start_date=>Sat, 01 Dec 2012, :end_date=>Sat, 01 Dec 2012},
|
|
62
|
-
{:day=>337, :month_day=>2, :month=>12, :year=>2012, :start_date=>Sun, 02 Dec 2012, :end_date=>Sun, 02 Dec 2012},
|
|
63
|
-
{:day=>345, :month_day=>10, :month=>12, :year=>2012, :start_date=>Mon, 10 Dec 2012, :end_date=>Mon, 10 Dec 2012},
|
|
64
|
-
{:day=>346, :month_day=>11, :month=>12, :year=>2012, :start_date=>Tue, 11 Dec 2012, :end_date=>Tue, 11 Dec 2012},
|
|
65
|
-
{:day=>347, :month_day=>12, :month=>12, :year=>2012, :start_date=>Wed, 12 Dec 2012, :end_date=>Wed, 12 Dec 2012}
|
|
66
|
-
]
|
|
67
|
-
}
|
|
108
|
+
DateBreakup.between('01/01/2019', '03/01/2019').in_days
|
|
109
|
+
# => {
|
|
110
|
+
# years: [],
|
|
111
|
+
# months: [],
|
|
112
|
+
# weeks: [],
|
|
113
|
+
# days: [
|
|
114
|
+
# { day: 1, month_day: 1, month: 1, year: 2019, start_date: Tue 01 Jan 2019, end_date: Tue 01 Jan 2019 },
|
|
115
|
+
# { day: 2, month_day: 2, month: 1, year: 2019, start_date: Wed 02 Jan 2019, end_date: Wed 02 Jan 2019 },
|
|
116
|
+
# { day: 3, month_day: 3, month: 1, year: 2019, start_date: Thu 03 Jan 2019, end_date: Thu 03 Jan 2019 }
|
|
117
|
+
# ]
|
|
118
|
+
# }
|
|
68
119
|
```
|
|
69
120
|
|
|
70
|
-
|
|
121
|
+
## Development
|
|
122
|
+
|
|
123
|
+
This project uses [mise](https://mise.jdx.dev) to manage the Ruby version.
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
# Install the required Ruby version
|
|
127
|
+
mise install
|
|
128
|
+
|
|
129
|
+
# Install dependencies
|
|
130
|
+
bin/setup
|
|
71
131
|
|
|
72
|
-
|
|
132
|
+
# Run tests
|
|
133
|
+
bundle exec rspec
|
|
73
134
|
|
|
74
|
-
|
|
135
|
+
# Run a single spec file
|
|
136
|
+
bundle exec rspec spec/date_breakup_spec.rb
|
|
137
|
+
|
|
138
|
+
# Open an interactive console with the gem loaded
|
|
139
|
+
bin/console
|
|
140
|
+
|
|
141
|
+
# Install the gem locally
|
|
142
|
+
bundle exec rake install
|
|
143
|
+
```
|
|
75
144
|
|
|
76
145
|
## Contributing
|
|
77
146
|
|
|
78
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
|
147
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/HuzaifaSaifuddin/date_breakup.
|
|
79
148
|
|
|
80
149
|
## License
|
|
81
150
|
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
require 'date_breakup'
|
|
6
|
+
require 'pry'
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
-
|
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
-
# require "pry"
|
|
11
|
-
# Pry.start
|
|
12
|
-
|
|
13
|
-
require "irb"
|
|
14
|
-
IRB.start(__FILE__)
|
|
8
|
+
Pry.start
|
data/date_breakup.gemspec
CHANGED
|
@@ -1,41 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
|
|
2
|
-
lib = File.expand_path(
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
-
require
|
|
5
|
+
require 'date_breakup'
|
|
5
6
|
|
|
6
7
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name =
|
|
8
|
+
spec.name = 'date_breakup'
|
|
8
9
|
spec.version = DateBreakup::VERSION
|
|
9
|
-
spec.authors = [
|
|
10
|
-
spec.email = [
|
|
10
|
+
spec.authors = ['Huzaifa Saifuddin']
|
|
11
|
+
spec.email = ['huzaifasp18@gmail.com']
|
|
11
12
|
|
|
12
|
-
spec.summary =
|
|
13
|
-
spec.description =
|
|
14
|
-
spec.homepage =
|
|
15
|
-
spec.license =
|
|
13
|
+
spec.summary = 'Feed in 2 dates and get a breakup of dates grouped in years, months, weeks & days'
|
|
14
|
+
spec.description = 'Feed in 2 dates and get a breakup of dates grouped in years, months, weeks & days'
|
|
15
|
+
spec.homepage = 'https://github.com/HuzaifaSaifuddin/date_breakup'
|
|
16
|
+
spec.license = 'MIT'
|
|
16
17
|
|
|
17
18
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
|
18
19
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
|
19
20
|
if spec.respond_to?(:metadata)
|
|
20
|
-
spec.metadata[
|
|
21
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
|
21
22
|
else
|
|
22
|
-
raise
|
|
23
|
-
|
|
23
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
|
24
|
+
'public gem pushes.'
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
# Specify which files should be added to the gem when it is released.
|
|
27
28
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
28
|
-
spec.files
|
|
29
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
29
30
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
30
31
|
end
|
|
31
|
-
spec.bindir =
|
|
32
|
+
spec.bindir = 'exe'
|
|
32
33
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
33
|
-
spec.require_paths = [
|
|
34
|
+
spec.require_paths = ['lib']
|
|
35
|
+
spec.required_ruby_version = '>= 3.3'
|
|
34
36
|
|
|
35
|
-
spec.add_development_dependency
|
|
36
|
-
spec.add_development_dependency
|
|
37
|
-
spec.add_development_dependency
|
|
38
|
-
spec.add_development_dependency
|
|
39
|
-
|
|
40
|
-
spec.add_runtime_dependency 'date', '~> 2.0'
|
|
37
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
38
|
+
spec.add_development_dependency 'pry', '~> 0.14.1'
|
|
39
|
+
spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.3'
|
|
40
|
+
spec.add_development_dependency 'rspec', '~> 3.10'
|
|
41
|
+
spec.add_development_dependency 'rubocop', '~> 1.65'
|
|
41
42
|
end
|
data/lib/date_breakup.rb
CHANGED
|
@@ -1,183 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
require "time_difference"
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
class Range
|
|
6
|
-
private_class_method :new
|
|
3
|
+
require 'date'
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def get_years
|
|
13
|
-
get_year_array(@date1, @date2)
|
|
14
|
-
|
|
15
|
-
output = { years: @year_array, months: @month_array, weeks: @week_array, days: @day_array }
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def get_months
|
|
19
|
-
get_month_array(@date1, @date2)
|
|
20
|
-
|
|
21
|
-
output = { years: @year_array, months: @month_array, weeks: @week_array, days: @day_array }
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def get_weeks
|
|
25
|
-
get_week_array(@date1, @date2)
|
|
26
|
-
|
|
27
|
-
output = { years: @year_array, months: @month_array, weeks: @week_array, days: @day_array }
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def get_days
|
|
31
|
-
get_day_array(@date1, @date2)
|
|
32
|
-
|
|
33
|
-
output = { years: @year_array, months: @month_array, weeks: @week_array, days: @day_array }
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
private
|
|
37
|
-
|
|
38
|
-
def initialize(date1, date2)
|
|
39
|
-
@date1 = date1
|
|
40
|
-
@date2 = date2
|
|
41
|
-
@year_array = Array.new
|
|
42
|
-
@month_array = Array.new
|
|
43
|
-
@week_array = Array.new
|
|
44
|
-
@day_array = Array.new
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def get_year_array(date, end_date)
|
|
48
|
-
move_to_date = true
|
|
49
|
-
# YEAR
|
|
50
|
-
if move_to_date
|
|
51
|
-
if date.beginning_of_year == date
|
|
52
|
-
if date.end_of_year <= @date2
|
|
53
|
-
date, move_to_date = get_year_data(date)
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# MONTH
|
|
59
|
-
if move_to_date
|
|
60
|
-
if date.beginning_of_month == date
|
|
61
|
-
if date.end_of_month <= @date2
|
|
62
|
-
date, move_to_date = get_month_data(date)
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Week
|
|
68
|
-
if move_to_date
|
|
69
|
-
if date.beginning_of_week == date && date.end_of_week <= @date2
|
|
70
|
-
if date.beginning_of_week.month == date.end_of_week.month || date.end_of_week.end_of_month >= @date2
|
|
71
|
-
date, move_to_date = get_week_data(date)
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# DAY
|
|
77
|
-
if move_to_date
|
|
78
|
-
date, move_to_date = get_date_data(date)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
if date <= end_date
|
|
82
|
-
get_year_array(date, end_date)
|
|
83
|
-
end
|
|
84
|
-
end
|
|
5
|
+
class DateBreakup
|
|
6
|
+
VERSION = '3.1.0'
|
|
85
7
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if move_to_date
|
|
90
|
-
if date.beginning_of_month == date
|
|
91
|
-
if date.end_of_month <= @date2
|
|
92
|
-
date, move_to_date = get_month_data(date)
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# Week
|
|
98
|
-
if move_to_date
|
|
99
|
-
if date.beginning_of_week == date && date.end_of_week <= @date2
|
|
100
|
-
if date.beginning_of_week.month == date.end_of_week.month || date.end_of_week.end_of_month >= @date2
|
|
101
|
-
date, move_to_date = get_week_data(date)
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# DAY
|
|
107
|
-
if move_to_date
|
|
108
|
-
date, move_to_date = get_date_data(date)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
if date <= end_date
|
|
112
|
-
get_month_array(date, end_date)
|
|
113
|
-
end
|
|
114
|
-
end
|
|
8
|
+
def self.between(start_date, end_date)
|
|
9
|
+
new(coerce_to_date(start_date), coerce_to_date(end_date))
|
|
10
|
+
end
|
|
115
11
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
# Week
|
|
119
|
-
if move_to_date
|
|
120
|
-
if date.beginning_of_week == date && date.end_of_week <= @date2
|
|
121
|
-
date, move_to_date = get_week_data(date)
|
|
122
|
-
end
|
|
123
|
-
end
|
|
12
|
+
def initialize(start_date, end_date)
|
|
13
|
+
raise ArgumentError, 'start_date must be before or equal to end_date' if start_date > end_date
|
|
124
14
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
end
|
|
15
|
+
@start_date = start_date
|
|
16
|
+
@end_date = end_date
|
|
17
|
+
end
|
|
129
18
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
19
|
+
def in_years = build_breakdown(years: true, months: true, weeks: true)
|
|
20
|
+
def in_months = build_breakdown(years: false, months: true, weeks: true)
|
|
21
|
+
def in_weeks = build_breakdown(years: false, months: false, weeks: true)
|
|
22
|
+
def in_days = build_breakdown(years: false, months: false, weeks: false)
|
|
23
|
+
|
|
24
|
+
private_class_method def self.coerce_to_date(value)
|
|
25
|
+
case value
|
|
26
|
+
when Date then value
|
|
27
|
+
when Time then value.to_date
|
|
28
|
+
when String then Date.parse(value)
|
|
29
|
+
else raise ArgumentError, "expected a Date, Time, or String, got #{value.class}"
|
|
133
30
|
end
|
|
31
|
+
end
|
|
134
32
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def build_breakdown(years: false, months: false, weeks: false)
|
|
36
|
+
y = []
|
|
37
|
+
m = []
|
|
38
|
+
w = []
|
|
39
|
+
d = []
|
|
40
|
+
date = @start_date
|
|
41
|
+
|
|
42
|
+
while date <= @end_date
|
|
43
|
+
year_end = Date.new(date.year, 12, 31)
|
|
44
|
+
month_end = Date.new(date.year, date.month, -1)
|
|
45
|
+
week_start = date - (date.cwday - 1)
|
|
46
|
+
week_end = date + (7 - date.cwday)
|
|
47
|
+
|
|
48
|
+
if years && date == Date.new(date.year, 1, 1) && @end_date >= year_end
|
|
49
|
+
y << { year: date.year, start_date: date, end_date: year_end }
|
|
50
|
+
date = year_end + 1
|
|
51
|
+
elsif months && date == Date.new(date.year, date.month, 1) && @end_date >= month_end
|
|
52
|
+
m << { month: date.month, year: date.year, start_date: date, end_date: month_end }
|
|
53
|
+
date = month_end + 1
|
|
54
|
+
elsif weeks && date == week_start && @end_date >= week_end
|
|
55
|
+
w << { week: date.cweek, month: date.month, year: date.year, start_date: date, end_date: week_end }
|
|
56
|
+
date = week_end + 1
|
|
57
|
+
else
|
|
58
|
+
d << { day: date.yday, month_day: date.mday, month: date.month, year: date.year,
|
|
59
|
+
start_date: date, end_date: date }
|
|
60
|
+
date += 1
|
|
144
61
|
end
|
|
145
62
|
end
|
|
146
63
|
|
|
147
|
-
|
|
148
|
-
year_hash = { year: date.year, start_date: date, end_date: date.end_of_year }
|
|
149
|
-
@year_array << year_hash
|
|
150
|
-
new_date = date.end_of_year + 1.day
|
|
151
|
-
move_to_date = false
|
|
152
|
-
|
|
153
|
-
return new_date, move_to_date
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def get_month_data(date)
|
|
157
|
-
month_hash = { month: date.month, year: date.year, start_date: date, end_date: date.end_of_month }
|
|
158
|
-
@month_array << month_hash
|
|
159
|
-
new_date = date.end_of_month + 1.day
|
|
160
|
-
move_to_date = false
|
|
161
|
-
|
|
162
|
-
return new_date, move_to_date
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def get_week_data(date)
|
|
166
|
-
week_hash = { week: date.cweek, month: date.month, year: date.year, start_date: date, end_date: date.end_of_week }
|
|
167
|
-
@week_array << week_hash
|
|
168
|
-
new_date = date.end_of_week + 1.day
|
|
169
|
-
move_to_date = false
|
|
170
|
-
|
|
171
|
-
return new_date, move_to_date
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def get_date_data(date)
|
|
175
|
-
day_hash = { day: date.yday, month_day: date.mday, month: date.month, year: date.year, start_date: date, end_date: date }
|
|
176
|
-
@day_array << day_hash
|
|
177
|
-
new_date = date + 1.day
|
|
178
|
-
move_to_date = false
|
|
179
|
-
|
|
180
|
-
return new_date, move_to_date
|
|
181
|
-
end
|
|
64
|
+
{ years: y, months: m, weeks: w, days: d }
|
|
182
65
|
end
|
|
183
66
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: date_breakup
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Huzaifa Saifuddin
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-05-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -16,82 +16,94 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '2.0'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '2.0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: pry
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
33
|
+
version: 0.14.1
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
40
|
+
version: 0.14.1
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: rake
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
47
|
+
version: '13.0'
|
|
48
|
+
- - ">="
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: 13.0.3
|
|
48
51
|
type: :development
|
|
49
52
|
prerelease: false
|
|
50
53
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
54
|
requirements:
|
|
52
55
|
- - "~>"
|
|
53
56
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
57
|
+
version: '13.0'
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: 13.0.3
|
|
55
61
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
62
|
+
name: rspec
|
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
|
58
64
|
requirements:
|
|
59
65
|
- - "~>"
|
|
60
66
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '
|
|
67
|
+
version: '3.10'
|
|
62
68
|
type: :development
|
|
63
69
|
prerelease: false
|
|
64
70
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
71
|
requirements:
|
|
66
72
|
- - "~>"
|
|
67
73
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '
|
|
74
|
+
version: '3.10'
|
|
69
75
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
76
|
+
name: rubocop
|
|
71
77
|
requirement: !ruby/object:Gem::Requirement
|
|
72
78
|
requirements:
|
|
73
79
|
- - "~>"
|
|
74
80
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '
|
|
76
|
-
type: :
|
|
81
|
+
version: '1.65'
|
|
82
|
+
type: :development
|
|
77
83
|
prerelease: false
|
|
78
84
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
85
|
requirements:
|
|
80
86
|
- - "~>"
|
|
81
87
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
88
|
+
version: '1.65'
|
|
83
89
|
description: Feed in 2 dates and get a breakup of dates grouped in years, months,
|
|
84
90
|
weeks & days
|
|
85
91
|
email:
|
|
86
|
-
-
|
|
92
|
+
- huzaifasp18@gmail.com
|
|
87
93
|
executables: []
|
|
88
94
|
extensions: []
|
|
89
95
|
extra_rdoc_files: []
|
|
90
96
|
files:
|
|
97
|
+
- ".claude/settings.json"
|
|
98
|
+
- ".github/workflows/ci.yml"
|
|
91
99
|
- ".gitignore"
|
|
100
|
+
- ".mise.toml"
|
|
92
101
|
- ".rspec"
|
|
93
|
-
- ".
|
|
102
|
+
- ".rubocop.yml"
|
|
103
|
+
- CHANGELOG.md
|
|
104
|
+
- CLAUDE.md
|
|
94
105
|
- Gemfile
|
|
106
|
+
- Gemfile.lock
|
|
95
107
|
- LICENSE.txt
|
|
96
108
|
- README.md
|
|
97
109
|
- Rakefile
|
|
@@ -99,14 +111,12 @@ files:
|
|
|
99
111
|
- bin/setup
|
|
100
112
|
- date_breakup.gemspec
|
|
101
113
|
- lib/date_breakup.rb
|
|
102
|
-
- lib/date_breakup/version.rb
|
|
103
|
-
- lib/date_breakup_v1.rb
|
|
104
114
|
homepage: https://github.com/HuzaifaSaifuddin/date_breakup
|
|
105
115
|
licenses:
|
|
106
116
|
- MIT
|
|
107
117
|
metadata:
|
|
108
118
|
allowed_push_host: https://rubygems.org
|
|
109
|
-
post_install_message:
|
|
119
|
+
post_install_message:
|
|
110
120
|
rdoc_options: []
|
|
111
121
|
require_paths:
|
|
112
122
|
- lib
|
|
@@ -114,16 +124,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
114
124
|
requirements:
|
|
115
125
|
- - ">="
|
|
116
126
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: '
|
|
127
|
+
version: '3.3'
|
|
118
128
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
129
|
requirements:
|
|
120
130
|
- - ">="
|
|
121
131
|
- !ruby/object:Gem::Version
|
|
122
132
|
version: '0'
|
|
123
133
|
requirements: []
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
signing_key:
|
|
134
|
+
rubygems_version: 3.5.22
|
|
135
|
+
signing_key:
|
|
127
136
|
specification_version: 4
|
|
128
137
|
summary: Feed in 2 dates and get a breakup of dates grouped in years, months, weeks
|
|
129
138
|
& days
|
data/.travis.yml
DELETED
data/lib/date_breakup/version.rb
DELETED
data/lib/date_breakup_v1.rb
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
require "date_breakup/version"
|
|
2
|
-
require "time_difference"
|
|
3
|
-
|
|
4
|
-
module DateBreakup
|
|
5
|
-
class Range
|
|
6
|
-
private_class_method :new
|
|
7
|
-
|
|
8
|
-
def self.between(date1, date2)
|
|
9
|
-
new(Date.parse(date1), Date.parse(date2))
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def get_accurate
|
|
13
|
-
years, remaining_dates_year = get_years(@date1, @date2)
|
|
14
|
-
|
|
15
|
-
months, remaining_dates_month = get_months(remaining_dates_year)
|
|
16
|
-
|
|
17
|
-
weeks, remaining_dates_week = get_weeks(remaining_dates_month)
|
|
18
|
-
|
|
19
|
-
days, remaining_dates_days = get_days(remaining_dates_week)
|
|
20
|
-
|
|
21
|
-
output = { years: years, months: months, weeks: weeks, days: days }
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
private
|
|
25
|
-
|
|
26
|
-
def initialize(date1, date2)
|
|
27
|
-
@date1 = date1
|
|
28
|
-
@date2 = date2
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def get_years(date1, date2)
|
|
32
|
-
year_array = []
|
|
33
|
-
remaining_dates = []
|
|
34
|
-
|
|
35
|
-
if date1.beginning_of_year == date1 && date1.end_of_year <= date2
|
|
36
|
-
year_hash = { year: date1.year, start_date: date1.beginning_of_year, end_date: date1.end_of_year }
|
|
37
|
-
year_array << year_hash
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
get_year_range(date1, date2, year_array, year_hash)
|
|
41
|
-
|
|
42
|
-
if year_array.count > 0
|
|
43
|
-
if(date1 != year_array[0][:start_date])
|
|
44
|
-
remaining_dates_hash = { date1: date1, date2: year_array[0][:start_date] - 1 }
|
|
45
|
-
remaining_dates << remaining_dates_hash
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
if(date2 != year_array[-1][:end_date])
|
|
49
|
-
remaining_dates_hash = { date1: year_array[-1][:end_date] + 1, date2: date2 }
|
|
50
|
-
remaining_dates << remaining_dates_hash
|
|
51
|
-
end
|
|
52
|
-
else
|
|
53
|
-
remaining_dates << { date1: date1, date2: date2 }
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
return year_array, remaining_dates
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def get_months(remaining_dates_year)
|
|
60
|
-
month_array = []
|
|
61
|
-
remaining_dates = []
|
|
62
|
-
|
|
63
|
-
remaining_dates_year.each do |rd|
|
|
64
|
-
date1, date2 = rd[:date1], rd[:date2]
|
|
65
|
-
if date1.beginning_of_month == date1 && date1.end_of_month <= date2
|
|
66
|
-
month_hash = { month: date1.month, year: date1.year, start_date: date1.beginning_of_month, end_date: date1.end_of_month }
|
|
67
|
-
month_array << month_hash
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
get_month_range(date1, date2, month_array, month_hash)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if month_array.count > 0
|
|
75
|
-
month_arrx1 = month_array.sort_by{ |ma| ma[:start_date] }.select{ |wa| wa[:year] == remaining_dates_year[0][:date1].year }.first
|
|
76
|
-
|
|
77
|
-
if month_arrx1
|
|
78
|
-
if(remaining_dates_year[0][:date1] != month_arrx1[:start_date])
|
|
79
|
-
remaining_dates_hash = { date1: remaining_dates_year[0][:date1], date2: month_arrx1[:start_date] - 1 }
|
|
80
|
-
remaining_dates << remaining_dates_hash
|
|
81
|
-
end
|
|
82
|
-
else
|
|
83
|
-
remaining_dates_hash = { date1: remaining_dates_year[0][:date1], date2: remaining_dates_year[0][:date2] }
|
|
84
|
-
remaining_dates << remaining_dates_hash
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
month_arrx2 = month_array.sort_by{ |ma| ma[:start_date] }.select{ |wa| wa[:year] == remaining_dates_year[-1][:date2].year }.last
|
|
88
|
-
if month_arrx2
|
|
89
|
-
if(remaining_dates_year[-1][:date2] != month_arrx2[:end_date])
|
|
90
|
-
remaining_dates_hash = { date1: month_arrx2[:end_date] + 1, date2: remaining_dates_year[-1][:date2] }
|
|
91
|
-
remaining_dates << remaining_dates_hash
|
|
92
|
-
end
|
|
93
|
-
else
|
|
94
|
-
remaining_dates_hash = { date1: remaining_dates_year[-1][:date1], date2: remaining_dates_year[-1][:date2] }
|
|
95
|
-
remaining_dates << remaining_dates_hash
|
|
96
|
-
end
|
|
97
|
-
else
|
|
98
|
-
remaining_dates = remaining_dates_year
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
return month_array, remaining_dates
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def get_weeks(remaining_dates_month)
|
|
105
|
-
week_array = []
|
|
106
|
-
remaining_dates = []
|
|
107
|
-
|
|
108
|
-
remaining_dates_month.each do |rd|
|
|
109
|
-
date1, date2 = rd[:date1], rd[:date2]
|
|
110
|
-
if date1.beginning_of_week == date1 && date1.end_of_week <= date2
|
|
111
|
-
week_hash = { week: date1.cweek, month: date1.month, year: date1.year, start_date: date1.beginning_of_week, end_date: date1.end_of_week }
|
|
112
|
-
week_array << week_hash
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
get_week_range(date1, date2, week_array, week_hash)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
if week_array.count > 0
|
|
119
|
-
week_arrx1 = week_array.sort_by{ |ma| ma[:start_date] }.select{ |wa| wa[:month] == remaining_dates_month[0][:date1].month }.first
|
|
120
|
-
if week_arrx1
|
|
121
|
-
if(remaining_dates_month[0][:date1] != week_arrx1[:start_date])
|
|
122
|
-
remaining_dates_hash = { date1: remaining_dates_month[0][:date1], date2: week_arrx1[:start_date] - 1 }
|
|
123
|
-
remaining_dates << remaining_dates_hash
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
week_arrx2 = week_array.sort_by{ |ma| ma[:start_date] }.select{ |wa| wa[:month] == remaining_dates_month[0][:date2].month }.last
|
|
128
|
-
if week_arrx2
|
|
129
|
-
if(remaining_dates_month[0][:date2] != week_arrx2[:end_date])
|
|
130
|
-
remaining_dates_hash = { date1: week_arrx2[:end_date] + 1, date2: remaining_dates_month[0][:date2] }
|
|
131
|
-
remaining_dates << remaining_dates_hash
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
week_arrx3 = week_array.sort_by{ |ma| ma[:start_date] }.select{ |wa| wa[:month] == remaining_dates_month[-1][:date1].month }.first
|
|
136
|
-
if week_arrx3
|
|
137
|
-
if(remaining_dates_month[0][:date1] != week_arrx3[:end_date])
|
|
138
|
-
remaining_dates_hash = { date1: remaining_dates_month[-1][:date1], date2: week_arrx3[:start_date] - 1 }
|
|
139
|
-
remaining_dates << remaining_dates_hash
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
week_arrx4 = week_array.sort_by{ |ma| ma[:start_date] }.select{ |wa| wa[:month] == remaining_dates_month[-1][:date1].month }.last
|
|
144
|
-
if week_arrx4
|
|
145
|
-
if(remaining_dates_month[-1][:date2] != week_arrx4[:end_date])
|
|
146
|
-
remaining_dates_hash = { date1: week_arrx4[:end_date] + 1, date2: remaining_dates_month[-1][:date2] }
|
|
147
|
-
remaining_dates << remaining_dates_hash
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
else
|
|
151
|
-
remaining_dates = remaining_dates_month
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
return week_array, remaining_dates
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def get_days(remaining_dates_week)
|
|
158
|
-
day_array = []
|
|
159
|
-
remaining_dates = []
|
|
160
|
-
|
|
161
|
-
remaining_dates_week.each do |rd|
|
|
162
|
-
date1, date2 = rd[:date1], rd[:date2]
|
|
163
|
-
dates = (date1).upto(date2).to_a
|
|
164
|
-
|
|
165
|
-
dates.each do |date|
|
|
166
|
-
unless day_array.find{ |da| da[:start_date] == date }.present?
|
|
167
|
-
day_hash = { day: date.yday, month_day: date.mday, month: date.month, year: date.year, start_date: date, end_date: date }
|
|
168
|
-
day_array << day_hash
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
return day_array, remaining_dates
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
def get_year_range(date1, date2, year_array, year_hash)
|
|
177
|
-
next_year = (date1.end_of_year + 1.day)
|
|
178
|
-
end_next_year = next_year.end_of_year
|
|
179
|
-
if end_next_year <= date2
|
|
180
|
-
year = end_next_year.year
|
|
181
|
-
start_date = next_year.beginning_of_year
|
|
182
|
-
end_date = end_next_year
|
|
183
|
-
year_hash = { year: year, start_date: start_date, end_date: end_date }
|
|
184
|
-
year_array << year_hash
|
|
185
|
-
get_year_range(next_year, date2, year_array, year_hash)
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
def get_month_range(date1, date2, month_array, month_hash)
|
|
190
|
-
next_month = (date1.end_of_month + 1.day)
|
|
191
|
-
end_next_month = next_month.end_of_month
|
|
192
|
-
if end_next_month <= date2
|
|
193
|
-
month = end_next_month.month
|
|
194
|
-
start_date = next_month.beginning_of_month
|
|
195
|
-
end_date = end_next_month
|
|
196
|
-
month_hash = { month: month, year: end_next_month.year, start_date: start_date, end_date: end_date }
|
|
197
|
-
month_array << month_hash
|
|
198
|
-
get_month_range(next_month, date2, month_array, month_hash)
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def get_week_range(date1, date2, week_array, week_hash)
|
|
203
|
-
next_week = (date1.end_of_week + 1.day)
|
|
204
|
-
end_next_week = next_week.end_of_week
|
|
205
|
-
if end_next_week <= date2
|
|
206
|
-
week = end_next_week.cweek
|
|
207
|
-
start_date = next_week.beginning_of_week
|
|
208
|
-
end_date = end_next_week
|
|
209
|
-
week_hash = { week: week, month: end_next_week.month, year: end_next_week.year, start_date: start_date, end_date: end_date }
|
|
210
|
-
week_array << week_hash
|
|
211
|
-
get_week_range(next_week, date2, week_array, week_hash)
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
end
|
|
215
|
-
end
|