philiprehberger-cron_parser 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3be8924f48f35f97ea4d356f5368d7907cf23bda63af8af43c4b3776f1a47a69
4
- data.tar.gz: 0d0284d3e84fe3b93db4911a30149333bf0faaba73f2857ec28ae95f83455509
3
+ metadata.gz: 2d7e8b08d65ab34dacc640a348cd965a7a604840a0a5c10ad13327740ddb323e
4
+ data.tar.gz: 353889bda7ae0edd7074fc0a3a84056dff6ca731ab5daa65fa4c4ace54cedacf
5
5
  SHA512:
6
- metadata.gz: 4cf277261fcf00a553dc1defe27a24b74ace4d34f7760e5033d5b52dbbb2fa87bacb0a36b32e8847bd3af4e2d93381caf3fa17b8f5e6fa0953fc32a3105f2b01
7
- data.tar.gz: 6e5f421543e3a2871f1b8e068f12dab5ebec5586ff18ee297dcbca94261cca57e931c72e00af468a783170462edd333939b1e1370d715a5770b32fb3f457f4fc
6
+ metadata.gz: b3a8cef0c91c1f4056005b846d1b1d9960abca68cb1821c1fe602b9d4f8e9b73e4d70df8b11fd4971b46e0f4c65fbd9bfa6c466713f3a664037f1b373de93821
7
+ data.tar.gz: a89b2d2bef776c9f2ff5f0edba5fd163db301e0566ed0a9a6062b5af2633ec45731f90fae38e46ef4a4cf7f376804b7a21f6bff9f42b334527214cd540e4ceb8
data/CHANGELOG.md CHANGED
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.5.0] - 2026-05-12
11
+
12
+ ### Added
13
+ - `Expression#each_in(from:, to:, &block)` iterator over every matching occurrence in an inclusive window; returns an Enumerator when no block is given so callers can chain `Enumerable` methods like `first`, `take`, and `lazy`
14
+
10
15
  ## [0.4.0] - 2026-04-30
11
16
 
12
17
  ### Added
data/README.md CHANGED
@@ -58,6 +58,20 @@ to = Time.new(2026, 4, 30, 10, 0, 0)
58
58
  cron.count_in(from: from, to: to) # => 5
59
59
  ```
60
60
 
61
+ ### Iterating Occurrences in a Window
62
+
63
+ ```ruby
64
+ cron = Philiprehberger::CronParser.new('*/15 * * * *')
65
+ from = Time.new(2026, 4, 30, 9, 0, 0)
66
+ to = Time.new(2026, 4, 30, 10, 0, 0)
67
+
68
+ cron.each_in(from: from, to: to) { |t| puts t }
69
+
70
+ # Without a block, returns an Enumerator
71
+ cron.each_in(from: from, to: to).first(2)
72
+ # => [2026-04-30 09:00:00, 2026-04-30 09:15:00]
73
+ ```
74
+
61
75
  ### Human-Readable Description
62
76
 
63
77
  ```ruby
@@ -128,6 +142,7 @@ Philiprehberger::CronParser.new('0 9 * * MON-FRI') # named weekdays
128
142
  | `Expression#prev(from:)` | Calculate the previous matching time |
129
143
  | `Expression#next_n(n, from:)` | Calculate the next N matching times |
130
144
  | `Expression#count_in(from:, to:)` | Count occurrences within an inclusive `[from, to]` window |
145
+ | `Expression#each_in(from:, to:, &block)` | Yield each matching occurrence in `[from, to]`; returns an Enumerator without a block |
131
146
  | `Expression#matches?(time)` | Check if a time matches the expression |
132
147
  | `Expression#human_readable` | Human-readable description of the expression |
133
148
  | `Expression#description` | Alias for `human_readable` |
@@ -130,6 +130,32 @@ module Philiprehberger
130
130
  count
131
131
  end
132
132
 
133
+ # Iterate every matching time within an inclusive `[from, to]` window.
134
+ #
135
+ # When called with a block, yields each occurrence and returns `self`.
136
+ # Without a block, returns an `Enumerator` so callers can chain `Enumerable`
137
+ # methods (`take`, `lazy`, `to_a`, ...).
138
+ #
139
+ # @param from [Time] start of the window
140
+ # @param to [Time] end of the window
141
+ # @yieldparam time [Time] a matching occurrence
142
+ # @return [self, Enumerator] self when a block is given, otherwise an Enumerator
143
+ # @raise [Error] if `to` is earlier than `from`
144
+ def each_in(from:, to:, &block)
145
+ raise Error, '`to` must be greater than or equal to `from`' if to < from
146
+
147
+ return enum_for(:each_in, from: from, to: to) unless block
148
+
149
+ cursor = round_to_minute(from) - 60
150
+ loop do
151
+ cursor = self.next(from: cursor)
152
+ break if cursor > to
153
+
154
+ block.call(cursor)
155
+ end
156
+ self
157
+ end
158
+
133
159
  # Return a human-readable description of the expression
134
160
  #
135
161
  # @return [String]
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Philiprehberger
4
4
  module CronParser
5
- VERSION = '0.4.0'
5
+ VERSION = '0.5.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: philiprehberger-cron_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philip Rehberger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-05-01 00:00:00.000000000 Z
11
+ date: 2026-05-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Parse standard 5-field cron expressions and calculate next/previous occurrences,
14
14
  match times against patterns, and generate human-readable descriptions.