blackcal 0.3.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|