blackcal 0.3.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 +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +47 -10
- data/blackcal.gemspec +3 -3
- data/lib/blackcal/array_util.rb +15 -0
- data/lib/blackcal/builder.rb +74 -0
- data/lib/blackcal/range/day_range.rb +9 -5
- data/lib/blackcal/range/month_range.rb +11 -2
- data/lib/blackcal/range/time_range.rb +1 -1
- data/lib/blackcal/range/weekday_range.rb +11 -2
- data/lib/blackcal/range/weeks_of_month_range.rb +41 -0
- data/lib/blackcal/schedule.rb +36 -11
- data/lib/blackcal/time_util.rb +22 -0
- data/lib/blackcal/version.rb +1 -1
- data/lib/blackcal.rb +24 -2
- metadata +31 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6791c2ac53fda72382a38189234041baf6d19defb4f107ca0c20daf65bec80e2
|
4
|
+
data.tar.gz: '0923ab5b74740c318f800252df81f1891351cece635b92390bec242b84f50db3'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a79edd8fca16b0e38eaf636130c9c9da9c0aada8cd412421bed2e3a61240ac55ac01fda22c59e8f43da62aec41fcf74ced864368cbb48aaa2fba80b68bc6bb31
|
7
|
+
data.tar.gz: 2fe7fee65fd27db06e18f38afe536c40e146bb82a97af8da75d150d5200cc6d3d7986989ab9e9ffc0b7836a447f741a6cc0f6fb83ddc9f114fcfee2f167e8b81
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
# v0.5.0
|
4
|
+
|
5
|
+
* Add support for builder/DSL pattern
|
6
|
+
* Rename `start_hour` => `start_time_of_day`
|
7
|
+
* Rename `finish_hour` => `finish_time_of_day`
|
8
|
+
* Add attribute readers for `Schedule` data
|
9
|
+
* Support array of ranges in `DayRange` and `WeeksOfMonthRange`.
|
10
|
+
* Rename `WeekOfMonthRange` to `WeeksOfMonthRange`
|
11
|
+
* Support weekday and month numbers - [Fixes #7](https://github.com/buren/blackcal/issues/7)
|
12
|
+
|
13
|
+
# v0.4.0
|
14
|
+
|
15
|
+
* Add support for weeks of month - [PR #6](https://github.com/buren/blackcal/pull/6)
|
16
|
+
|
3
17
|
# v0.3.0
|
4
18
|
|
5
19
|
* Minute level resolution support
|
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
Create blacklist rules for calendars with ease. Supports recurring rules for certain weekdays, date numbers, hour of day.
|
4
4
|
|
5
|
+
Born from the idea of comparing schedules using matrix operations. This gem makes it easy to see whether if a time is covered by a certain schedule and generate a matrix representing what the schedule covers (hour our minute resolution).
|
6
|
+
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Add this line to your application's Gemfile:
|
@@ -20,6 +22,8 @@ Or install it yourself as:
|
|
20
22
|
|
21
23
|
## Usage
|
22
24
|
|
25
|
+
The main parts are `Blackcal#schedule` for generating a schedule, `schedule#cover?` to see whether a time is covered by schedule and finally `schedule#to_matrix` that generates a schedule with given time resolution (hour our minute).
|
26
|
+
|
23
27
|
Schedule Mondays and Tuesdays
|
24
28
|
```ruby
|
25
29
|
schedule = Blackcal.schedule(weekdays: [:monday, :tuesday])
|
@@ -31,11 +35,15 @@ schedule.cover?('2019-01-02 19:00')
|
|
31
35
|
|
32
36
|
Schedule between 6pm and 7am every day
|
33
37
|
```ruby
|
34
|
-
schedule = Blackcal.schedule(
|
38
|
+
schedule = Blackcal.schedule(start_time_of_day: 18, finish_hour_of_day: 7)
|
35
39
|
schedule.cover?('2019-01-01 19:00')
|
36
40
|
# => true
|
37
41
|
schedule.cover?('2019-01-01 11:00')
|
38
42
|
# => false
|
43
|
+
|
44
|
+
# minutes are supported too
|
45
|
+
eighteen_thirty = Blackcal::TimeOfDay.new(18, 30)
|
46
|
+
schedule = Blackcal.schedule(start_time_of_day: eighteen_thirty)
|
39
47
|
```
|
40
48
|
|
41
49
|
Schedule day 15 and 17 of month
|
@@ -47,33 +55,62 @@ schedule.cover?('2019-01-01 11:00')
|
|
47
55
|
# => false
|
48
56
|
```
|
49
57
|
|
50
|
-
|
58
|
+
Schedule first and third week of every month
|
59
|
+
```ruby
|
60
|
+
schedule = Blackcal.schedule(weeks_of_month: [1, 3])
|
61
|
+
schedule.cover?('2019-01-03 19:00')
|
62
|
+
# => true
|
63
|
+
schedule.cover?('2019-01-10 19:00')
|
64
|
+
# => false
|
65
|
+
```
|
66
|
+
|
67
|
+
Define when the schedule is active
|
68
|
+
```ruby
|
69
|
+
Blackcal.schedule(start_time: '2018-01-01 11:00', finish_time: '2019-01-01 11:00')
|
70
|
+
```
|
71
|
+
|
72
|
+
All options at once - schedule January, 3rd week, Mondays and Tuesdays, day 15-25, between 18pm and 7am
|
51
73
|
```ruby
|
52
74
|
schedule = Blackcal.schedule(
|
53
75
|
months: [:january],
|
76
|
+
weeks_of_month: [3],
|
54
77
|
weekdays: [:monday, :tuesday],
|
55
|
-
|
56
|
-
days:
|
78
|
+
start_time_of_day: 18, finish_hour_of_day: 7,
|
79
|
+
days: 15..25
|
57
80
|
)
|
58
|
-
schedule.cover?('
|
81
|
+
schedule.cover?('2018-01-16 06:00')
|
59
82
|
# => true
|
60
|
-
schedule.cover?('
|
83
|
+
schedule.cover?('2018-01-16 08:00')
|
61
84
|
# => false
|
62
85
|
```
|
63
86
|
|
64
|
-
|
87
|
+
_Note_: `#cover?` supports `String` and `Time` objects. `start_time_of_day` and `finish_hour_of_day` supports `Blackcal::TimeOfDay`, `Time` and `Integer` objects.
|
88
|
+
|
89
|
+
Builder pattern
|
65
90
|
```ruby
|
66
|
-
Blackcal.schedule
|
91
|
+
Blackcal.schedule do
|
92
|
+
months [:january]
|
93
|
+
weeks_of_month [3]
|
94
|
+
weekdays [:monday, :tuesday]
|
95
|
+
start_time_of_day 18
|
96
|
+
finish_hour_of_day 7
|
97
|
+
days 15..25
|
98
|
+
end
|
99
|
+
# you can, though not recommended, mix arguments with the
|
100
|
+
# builder data from the builder will override the arguments
|
101
|
+
Blackcal.schedule(days: [14, 21]) do
|
102
|
+
months [:january]
|
103
|
+
end
|
67
104
|
```
|
68
105
|
|
69
106
|
Matrix representation
|
70
107
|
```ruby
|
71
|
-
schedule = Blackcal.schedule(weekdays: :friday,
|
108
|
+
schedule = Blackcal.schedule(weekdays: :friday, start_time_of_day: 0, finish_hour_of_day: 14)
|
72
109
|
schedule.to_matrix(start_date: '2018-09-14', finish_date: '2018-09-16')
|
73
110
|
# => [[true, ...], [false, ...]]
|
74
111
|
|
75
112
|
# defaults to hour resolution, but you can get minute resolution too
|
76
|
-
schedule = Blackcal.schedule(weekdays: :friday,
|
113
|
+
schedule = Blackcal.schedule(weekdays: :friday, start_time_of_day: 0, finish_hour_of_day: 14)
|
77
114
|
schedule.to_matrix(resolution: :min, start_date: '2018-09-14', finish_date: '2018-09-16')
|
78
115
|
# => [[true, ...], [false, ...]]
|
79
116
|
```
|
data/blackcal.gemspec
CHANGED
@@ -24,11 +24,11 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
25
|
spec.require_paths = ['lib']
|
26
26
|
|
27
|
-
spec.add_development_dependency 'github-markup', '~> 2.0'
|
28
|
-
spec.add_development_dependency 'redcarpet', '~> 3.4'
|
29
|
-
spec.add_development_dependency 'simplecov', '~> 0.16'
|
30
27
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
31
28
|
spec.add_development_dependency 'byebug'
|
29
|
+
spec.add_development_dependency 'github-markup', '~> 2.0'
|
32
30
|
spec.add_development_dependency 'rake', '~> 10.0'
|
31
|
+
spec.add_development_dependency 'redcarpet', '~> 3.4'
|
33
32
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
33
|
+
spec.add_development_dependency 'simplecov', '~> 0.16'
|
34
34
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Blackcal
|
4
|
+
# Time utils module
|
5
|
+
module ArrayUtil
|
6
|
+
# @param [Array, Array<#to_a>, Object] data
|
7
|
+
# @return [Array]
|
8
|
+
def self.flatten(data)
|
9
|
+
Array(data).map do |object|
|
10
|
+
next object.to_a if object.respond_to?(:to_a)
|
11
|
+
object
|
12
|
+
end.flatten(1)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Blackcal
|
4
|
+
# Builder provides a DSL for schedule options
|
5
|
+
class Builder
|
6
|
+
# Enables a DSL for building schedule options
|
7
|
+
# @return [Builder]
|
8
|
+
# @example
|
9
|
+
# Blackcal.dsl do
|
10
|
+
# months [:january]
|
11
|
+
# days 15..25
|
12
|
+
# end
|
13
|
+
def self.dsl(&block)
|
14
|
+
new.tap { |b| b.instance_eval(&block) }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns a new instance of Builder
|
18
|
+
def initialize
|
19
|
+
@data = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param [Time, Date, String, nil] start_time
|
23
|
+
def start_time(start_time)
|
24
|
+
@data[:start_time] = start_time
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param [Time, Date, String, nil] finish_time
|
28
|
+
def finish_time(finish_time)
|
29
|
+
@data[:finish_time] = finish_time
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param [TimeOfDay, Time, Integer, nil] start_time_of_day
|
33
|
+
def start_time_of_day(start_time_of_day)
|
34
|
+
@data[:start_time_of_day] = start_time_of_day
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param [TimeOfDay, Time, Integer, nil] finish_hour_of_day
|
38
|
+
def finish_hour_of_day(finish_hour_of_day)
|
39
|
+
@data[:finish_hour_of_day] = finish_hour_of_day
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [Array<String>, Array<Symbol>, String, Symbol, nil] months
|
43
|
+
def months(*months)
|
44
|
+
@data[:months] = flat_array(months)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param [Array<String>, Array<Symbol>, String, Symbol, nil] weekdays
|
48
|
+
def weekdays(*weekdays)
|
49
|
+
@data[:weekdays] = flat_array(weekdays)
|
50
|
+
end
|
51
|
+
|
52
|
+
# @param [Array<Integer>, nil] weeks_of_month
|
53
|
+
def weeks_of_month(*weeks_of_month)
|
54
|
+
@data[:weeks_of_month] = flat_array(weeks_of_month)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param days [Array<Integer>, Integer, nil]
|
58
|
+
def days(*days)
|
59
|
+
@data[:days] = flat_array(days)
|
60
|
+
end
|
61
|
+
|
62
|
+
# The builder represented as a hash
|
63
|
+
# @return [Hash]
|
64
|
+
def to_h
|
65
|
+
@data
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def flat_array(array)
|
71
|
+
Array(array).flatten(1)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'blackcal/array_util'
|
4
|
+
|
3
5
|
module Blackcal
|
4
|
-
#
|
6
|
+
# Day range
|
5
7
|
class DayRange
|
6
8
|
include Enumerable
|
7
9
|
|
@@ -9,13 +11,15 @@ module Blackcal
|
|
9
11
|
attr_reader :numbers
|
10
12
|
|
11
13
|
# Initialize numbers range
|
12
|
-
# @param [Array<Integer>, Integer, nil] numbers
|
14
|
+
# @param [Array<#to_a>, Array<Integer>, Integer, nil] numbers
|
15
|
+
# @example
|
16
|
+
# DayRange.new(1)
|
13
17
|
# @example
|
14
|
-
#
|
18
|
+
# DayRange.new([1, 2])
|
15
19
|
# @example
|
16
|
-
#
|
20
|
+
# DayRange.new([9..10, 13..14])
|
17
21
|
def initialize(numbers)
|
18
|
-
@numbers =
|
22
|
+
@numbers = ArrayUtil.flatten(numbers) if numbers
|
19
23
|
end
|
20
24
|
|
21
25
|
# Returns true if it covers timestamp
|
@@ -21,17 +21,26 @@ module Blackcal
|
|
21
21
|
december: 12,
|
22
22
|
}.freeze
|
23
23
|
|
24
|
+
# Map month number to name
|
25
|
+
MONTH_INVERT_MAP = MONTH_MAP.invert.freeze
|
26
|
+
|
24
27
|
# @return [Array<Symbol>] months in range
|
25
28
|
attr_reader :months
|
26
29
|
|
27
30
|
# Initialize month range
|
28
|
-
# @param [Array<String>, Array<Symbol>, String, Symbol, nil] months
|
31
|
+
# @param [Array<String>, Array<Symbol>, Array<Integer>, String, Symbol, Integer, nil] months
|
29
32
|
# @example
|
30
33
|
# MonthRange.new(:january)
|
31
34
|
# @example
|
32
35
|
# MonthRange.new([:december, :january])
|
33
36
|
def initialize(months)
|
34
|
-
|
37
|
+
return unless months
|
38
|
+
|
39
|
+
@months = Array(months).map do |month|
|
40
|
+
next MONTH_INVERT_MAP.fetch(month) if month.is_a?(Integer)
|
41
|
+
|
42
|
+
month.downcase.to_sym
|
43
|
+
end
|
35
44
|
end
|
36
45
|
|
37
46
|
# Returns true if it covers timestamp
|
@@ -35,7 +35,7 @@ module Blackcal
|
|
35
35
|
resolution_multiplier = resolution == :hour ? 60 * 60 : 60
|
36
36
|
time_units = ((start - finish) / resolution_multiplier).abs.to_i
|
37
37
|
|
38
|
-
time_units
|
38
|
+
Array.new(time_units) do |time_unit|
|
39
39
|
start + (time_unit * resolution_multiplier)
|
40
40
|
end
|
41
41
|
end
|
@@ -16,17 +16,26 @@ module Blackcal
|
|
16
16
|
saturday: 6,
|
17
17
|
}.freeze
|
18
18
|
|
19
|
+
# Map weekday number to name
|
20
|
+
WEEKDAY_INVERT_MAP = WEEKDAY_MAP.invert.freeze
|
21
|
+
|
19
22
|
# @return [Array<Symbol>] weekdays in range
|
20
23
|
attr_reader :weekdays
|
21
24
|
|
22
25
|
# Initialize weekday range
|
23
|
-
# @param [Array<String>, Array<Symbol>, String, Symbol, nil] weekdays
|
26
|
+
# @param [Array<String>, Array<Symbol>, Array<Integer>, String, Symbol, Integer, nil] weekdays
|
24
27
|
# @example
|
25
28
|
# WeekdayRange.new(:monday)
|
26
29
|
# @example
|
27
30
|
# WeekdayRange.new([:monday, :thursday])
|
28
31
|
def initialize(weekdays)
|
29
|
-
|
32
|
+
return unless weekdays
|
33
|
+
|
34
|
+
@weekdays = Array(weekdays).map do |week|
|
35
|
+
next WEEKDAY_INVERT_MAP.fetch(week) if week.is_a?(Integer)
|
36
|
+
|
37
|
+
week.downcase.to_sym
|
38
|
+
end
|
30
39
|
end
|
31
40
|
|
32
41
|
# Returns true if it covers timestamp
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'blackcal/time_util'
|
4
|
+
require 'blackcal/array_util'
|
5
|
+
|
6
|
+
module Blackcal
|
7
|
+
# Week of month range
|
8
|
+
class WeeksOfMonthRange
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
# @return [Array<Integer>] numbers in range
|
12
|
+
attr_reader :numbers
|
13
|
+
|
14
|
+
# Initialize numbers range
|
15
|
+
# @param [Array<Integer>, Integer, nil] numbers
|
16
|
+
# @example
|
17
|
+
# WeeksOfMonthRange.new(1)
|
18
|
+
# @example
|
19
|
+
# WeeksOfMonthRange.new([1, 2])
|
20
|
+
def initialize(numbers)
|
21
|
+
@numbers = ArrayUtil.flatten(numbers) if numbers
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns true if it covers timestamp
|
25
|
+
# @return [Boolean]
|
26
|
+
def cover?(timestamp)
|
27
|
+
return false if numbers.nil? || numbers.empty?
|
28
|
+
|
29
|
+
numbers.include?(TimeUtil.week_of_month(timestamp))
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Array<Integer>] numbers in range
|
33
|
+
alias_method :to_a, :numbers
|
34
|
+
|
35
|
+
# Iterate over range
|
36
|
+
# @see #to_a
|
37
|
+
def each(&block)
|
38
|
+
to_a.each(&block)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/blackcal/schedule.rb
CHANGED
@@ -4,6 +4,7 @@ require 'time'
|
|
4
4
|
|
5
5
|
require 'blackcal/range/time_range'
|
6
6
|
require 'blackcal/range/time_of_day_range'
|
7
|
+
require 'blackcal/range/weeks_of_month_range'
|
7
8
|
require 'blackcal/range/weekday_range'
|
8
9
|
require 'blackcal/range/month_range'
|
9
10
|
require 'blackcal/range/day_range'
|
@@ -12,13 +13,32 @@ require 'blackcal/slot_matrix'
|
|
12
13
|
module Blackcal
|
13
14
|
# Represents a schedule
|
14
15
|
class Schedule
|
15
|
-
#
|
16
|
+
# @return [TimeRange] the time the schedule is active
|
17
|
+
attr_reader :time_range
|
18
|
+
|
19
|
+
# @return [MonthRange] months when this schedule is active
|
20
|
+
attr_reader :months
|
21
|
+
|
22
|
+
# @return [TimeOfDay] time of day when this schedule is active
|
23
|
+
attr_reader :time_of_day
|
24
|
+
|
25
|
+
# @return [WeeksOfMonthRange] weeks of month when this schedule is active
|
26
|
+
attr_reader :weeks_of_month
|
27
|
+
|
28
|
+
# @return [DayRange] days when this schedule is active
|
29
|
+
attr_reader :days
|
30
|
+
|
31
|
+
# @return [WeekdayRange] weekdays when this schedule is active
|
32
|
+
attr_reader :weekdays
|
33
|
+
|
34
|
+
# Initialize schedule
|
16
35
|
# @param start_time [Time, Date, String, nil]
|
17
36
|
# @param finish_time [Time, Date, String, nil]
|
18
|
-
# @param
|
19
|
-
# @param
|
37
|
+
# @param start_time_of_day [TimeOfDay, Time, Integer, nil]
|
38
|
+
# @param finish_hour_of_day [TimeOfDay, Time, Integer, nil]
|
20
39
|
# @param months [Array<String>, Array<Symbol>, String, Symbol, nil]
|
21
40
|
# @param weekdays [Array<String>, Array<Symbol>, String, Symbol, nil]
|
41
|
+
# @param weeks_of_month [Array<Integer>, nil]
|
22
42
|
# @param days [Array<Integer>, Integer, nil]
|
23
43
|
# @see TimeRange#initialize
|
24
44
|
# @see TimeOfDayRange#initialize
|
@@ -28,25 +48,29 @@ module Blackcal
|
|
28
48
|
def initialize(
|
29
49
|
start_time: nil,
|
30
50
|
finish_time: nil,
|
31
|
-
|
32
|
-
|
51
|
+
start_time_of_day: nil,
|
52
|
+
finish_hour_of_day: nil,
|
33
53
|
months: nil,
|
34
54
|
weekdays: nil,
|
35
|
-
|
55
|
+
weeks_of_month: nil,
|
36
56
|
days: nil
|
37
57
|
)
|
38
58
|
if start_time || finish_time
|
39
|
-
@
|
59
|
+
@time_range = TimeRange.new(parse_time(start_time), parse_time(finish_time))
|
40
60
|
end
|
41
61
|
|
42
|
-
if
|
43
|
-
@time_of_day = TimeOfDayRange.new(
|
62
|
+
if start_time_of_day || finish_hour_of_day
|
63
|
+
@time_of_day = TimeOfDayRange.new(start_time_of_day, finish_hour_of_day)
|
44
64
|
end
|
45
65
|
|
46
66
|
if months
|
47
67
|
@months = MonthRange.new(months)
|
48
68
|
end
|
49
69
|
|
70
|
+
if weeks_of_month
|
71
|
+
@weeks_of_month = WeeksOfMonthRange.new(weeks_of_month)
|
72
|
+
end
|
73
|
+
|
50
74
|
if weekdays
|
51
75
|
@weekdays = WeekdayRange.new(weekdays)
|
52
76
|
end
|
@@ -61,9 +85,9 @@ module Blackcal
|
|
61
85
|
# @return [Boolean]
|
62
86
|
def cover?(timestamp)
|
63
87
|
timestamp = parse_time(timestamp)
|
64
|
-
return false if @
|
88
|
+
return false if @time_range && !@time_range.cover?(timestamp)
|
65
89
|
|
66
|
-
ranges = [@months, @weekdays, @days, @time_of_day].compact
|
90
|
+
ranges = [@months, @weekdays, @days, @time_of_day, @weeks_of_month].compact
|
67
91
|
return false if ranges.empty?
|
68
92
|
|
69
93
|
ranges.all? { |range| range.cover?(timestamp) }
|
@@ -92,6 +116,7 @@ module Blackcal
|
|
92
116
|
|
93
117
|
def parse_time(time)
|
94
118
|
return Time.parse(time) if time.is_a?(String)
|
119
|
+
|
95
120
|
time
|
96
121
|
end
|
97
122
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Blackcal
|
4
|
+
# Time utils module
|
5
|
+
module TimeUtil
|
6
|
+
# Returns the week of month
|
7
|
+
# @return [Integer] week of month
|
8
|
+
# @see https://stackoverflow.com/a/30470158/955366
|
9
|
+
def self.week_of_month(date_or_time, start_day = :sunday)
|
10
|
+
date = date_or_time.to_date
|
11
|
+
week_start_format = start_day == :sunday ? '%U' : '%W'
|
12
|
+
|
13
|
+
week_of_month_start = Date.new(date.year, date.month, 1)
|
14
|
+
week_of_month_start_num = week_of_month_start.strftime(week_start_format).to_i
|
15
|
+
# Skip first week if doesn't contain a Thursday
|
16
|
+
week_of_month_start_num += 1 if week_of_month_start.wday > 4
|
17
|
+
|
18
|
+
month_week_index = date.strftime(week_start_format).to_i - week_of_month_start_num
|
19
|
+
month_week_index + 1 # Add 1 so that first week is 1 and not 0
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/blackcal/version.rb
CHANGED
data/lib/blackcal.rb
CHANGED
@@ -2,13 +2,35 @@
|
|
2
2
|
|
3
3
|
require 'blackcal/version'
|
4
4
|
require 'blackcal/schedule'
|
5
|
+
require 'blackcal/builder'
|
5
6
|
|
6
7
|
# Main module
|
7
8
|
module Blackcal
|
8
9
|
# Initialize schedule
|
9
10
|
# @return [Schedule]
|
11
|
+
# @example All options – using method arguments
|
12
|
+
# schedule = Blackcal.schedule(
|
13
|
+
# months: [:january],
|
14
|
+
# weeks_of_month: [3],
|
15
|
+
# weekdays: [:monday, :tuesday],
|
16
|
+
# start_time_of_day: 18,
|
17
|
+
# finish_hour_of_day: 7,
|
18
|
+
# days: (15..25).to_a
|
19
|
+
# )
|
20
|
+
# @example All options – using block builder
|
21
|
+
# schedule = Blackcal.schedule do
|
22
|
+
# months [:january]
|
23
|
+
# weeks_of_month [3]
|
24
|
+
# weekdays [:monday, :tuesday]
|
25
|
+
# start_time_of_day 18
|
26
|
+
# finish_hour_of_day 7
|
27
|
+
# days (15..25).to_a
|
28
|
+
# end
|
10
29
|
# @see Schedule#initialize
|
11
|
-
|
12
|
-
|
30
|
+
# @see Builder::dsl
|
31
|
+
def self.schedule(**keyword_args, &block)
|
32
|
+
schedule_args = keyword_args
|
33
|
+
schedule_args.merge!(Builder.dsl(&block).to_h) if block
|
34
|
+
Schedule.new(schedule_args)
|
13
35
|
end
|
14
36
|
end
|
metadata
CHANGED
@@ -1,113 +1,113 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blackcal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jacob Burenstam
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.16'
|
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: '1.16'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: byebug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
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'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: github-markup
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0
|
47
|
+
version: '2.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0
|
54
|
+
version: '2.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '10.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '10.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: redcarpet
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '3.4'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '3.4'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '3.0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '3.0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: simplecov
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '0.16'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
110
|
+
version: '0.16'
|
111
111
|
description: Create blacklist rules for calendars with ease. Supports recurring rules
|
112
112
|
for certain weekdays, date numbers, hour of day.
|
113
113
|
email:
|
@@ -131,14 +131,18 @@ files:
|
|
131
131
|
- bin/setup
|
132
132
|
- blackcal.gemspec
|
133
133
|
- lib/blackcal.rb
|
134
|
+
- lib/blackcal/array_util.rb
|
135
|
+
- lib/blackcal/builder.rb
|
134
136
|
- lib/blackcal/range/day_range.rb
|
135
137
|
- lib/blackcal/range/month_range.rb
|
136
138
|
- lib/blackcal/range/time_of_day_range.rb
|
137
139
|
- lib/blackcal/range/time_range.rb
|
138
140
|
- lib/blackcal/range/weekday_range.rb
|
141
|
+
- lib/blackcal/range/weeks_of_month_range.rb
|
139
142
|
- lib/blackcal/schedule.rb
|
140
143
|
- lib/blackcal/slot_matrix.rb
|
141
144
|
- lib/blackcal/time_of_day.rb
|
145
|
+
- lib/blackcal/time_util.rb
|
142
146
|
- lib/blackcal/version.rb
|
143
147
|
homepage: https://github.com/buren/blackcal
|
144
148
|
licenses:
|