make_a_calendar_toolkit 0.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 +7 -0
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/.rubocop.yml +27 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +6 -0
- data/CODE_OF_CONDUCT.md +7 -0
- data/CONTRIBUTING.md +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +21 -0
- data/LICENSE +21 -0
- data/README.md +154 -0
- data/Rakefile +11 -0
- data/SECURITY.md +5 -0
- data/docs/README.md +19 -0
- data/docs/advanced-examples.md +28 -0
- data/docs/api-reference.md +15 -0
- data/docs/architecture.md +5 -0
- data/docs/business-days.md +7 -0
- data/docs/calendar-rendering.md +5 -0
- data/docs/date-converters.md +5 -0
- data/docs/date-semantics.md +21 -0
- data/docs/fiscal-445.md +11 -0
- data/docs/getting-started.md +12 -0
- data/docs/holidays.md +7 -0
- data/docs/ics-export.md +5 -0
- data/docs/online-resources.md +12 -0
- data/docs/payroll-schedules.md +5 -0
- data/docs/printable-calendars.md +11 -0
- data/docs/recurring-dates.md +7 -0
- data/examples/01-monthly-printable.rb +3 -0
- data/examples/02-yearly-svg.rb +3 -0
- data/examples/03-federal-holidays.rb +4 -0
- data/examples/04-business-deadline.rb +4 -0
- data/examples/05-biweekly-payroll.rb +4 -0
- data/examples/06-rotating-shifts.rb +4 -0
- data/examples/07-fiscal-445.rb +4 -0
- data/examples/08-excel-serial.rb +3 -0
- data/examples/09-windows-filetime.rb +3 -0
- data/examples/10-holidays-ics.rb +4 -0
- data/examples/11-rails-style-service.rb +8 -0
- data/examples/12-ink-saver-planner.rb +3 -0
- data/exe/make-calendar +156 -0
- data/lib/make_a_calendar/calendar.rb +187 -0
- data/lib/make_a_calendar/converters.rb +90 -0
- data/lib/make_a_calendar/core/date_math.rb +86 -0
- data/lib/make_a_calendar/errors.rb +7 -0
- data/lib/make_a_calendar/export/ics.rb +52 -0
- data/lib/make_a_calendar/scheduling/business_days.rb +72 -0
- data/lib/make_a_calendar/scheduling/fiscal.rb +67 -0
- data/lib/make_a_calendar/scheduling/holidays.rb +60 -0
- data/lib/make_a_calendar/scheduling/recurring.rb +100 -0
- data/lib/make_a_calendar/version.rb +5 -0
- data/lib/make_a_calendar.rb +52 -0
- data/samples/calendar-2027.svg +982 -0
- data/samples/october-2027-ink-saver.svg +103 -0
- data/samples/october-2027.svg +103 -0
- data/samples/us-federal-holidays-2027.ics +83 -0
- data/samples/us-federal-holidays-2027.json +57 -0
- metadata +139 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 7b1145ce898bcbfe87749ff4eadb6dff4bb610b0abde0bb8feecf1b0ced9b5e3
|
|
4
|
+
data.tar.gz: 4060c5b3ade3f1a1cabcd6704d9d77b186ac5772151cafbf1bf22ffba22679fb
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ef360e90269be4d60dfda75aa937f991990bb1d4176b51a8c942e1ae8d08d3e6bda9fc7aee4f182d5dc6e662c5ef0327e8ff4753f00541866877e160eca5b930
|
|
7
|
+
data.tar.gz: 3e7d94d67856eab5874e7f83ba8ff292e04b5d7ea24f1c8632e6cfb5e41583755427c50e7777ce81148b39635ec923194d0448c4374fd32be8a4a30775c8eff5
|
data/.gitignore
ADDED
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--format documentation
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 2.7
|
|
3
|
+
NewCops: disable
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
Exclude:
|
|
6
|
+
- "vendor/**/*"
|
|
7
|
+
|
|
8
|
+
Layout/LineLength:
|
|
9
|
+
Max: 160
|
|
10
|
+
|
|
11
|
+
Metrics/AbcSize:
|
|
12
|
+
Enabled: false
|
|
13
|
+
|
|
14
|
+
Metrics/ClassLength:
|
|
15
|
+
Enabled: false
|
|
16
|
+
|
|
17
|
+
Metrics/MethodLength:
|
|
18
|
+
Max: 30
|
|
19
|
+
|
|
20
|
+
Style/Documentation:
|
|
21
|
+
Enabled: false
|
|
22
|
+
|
|
23
|
+
Style/GuardClause:
|
|
24
|
+
Enabled: false
|
|
25
|
+
|
|
26
|
+
Style/IfUnlessModifier:
|
|
27
|
+
Enabled: false
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.2.0
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — 2026-10-12
|
|
4
|
+
|
|
5
|
+
- Initial public release of calendar grids, date arithmetic, US federal holiday rules, business-day operations, recurring pay dates, shift schedules, NRF-style retail fiscal calendars, date converters, print-ready SVG/HTML, JSON/CSV, ICS, and CLI commands.
|
|
6
|
+
- Core operations use Ruby's standard library and run offline.
|
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
We are committed to a welcoming, respectful community. Be considerate, patient, and constructive. Harassment, discriminatory language, personal attacks, and unwanted attention are not acceptable.
|
|
4
|
+
|
|
5
|
+
Project maintainers may remove, edit, or reject contributions that do not follow this code and may temporarily or permanently exclude contributors for unacceptable behavior. Report concerns privately through the repository's GitHub contact options.
|
|
6
|
+
|
|
7
|
+
This code applies in project spaces and when someone is representing the project publicly.
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Bug reports and focused pull requests are welcome. Please include the Ruby version, a minimal reproduction, expected result, and actual result. Date changes should include independent calendar references or clearly stated rules.
|
|
4
|
+
|
|
5
|
+
Run the local checks with `ruby -Ilib spec/all_spec.rb`, `ruby -c` on changed Ruby files, and `gem build make_a_calendar_toolkit.gemspec`. Keep runtime dependencies at zero and document any new public behavior in the README or `docs/`.
|
|
6
|
+
|
|
7
|
+
Do not include credentials, private data, generated files that are not deliberate samples, or changes copied from the Make a Calendar website's private implementation.
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
make_a_calendar_toolkit (0.1.0)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
minitest (5.11.3)
|
|
10
|
+
rake (12.3.3)
|
|
11
|
+
|
|
12
|
+
PLATFORMS
|
|
13
|
+
ruby
|
|
14
|
+
|
|
15
|
+
DEPENDENCIES
|
|
16
|
+
make_a_calendar_toolkit!
|
|
17
|
+
minitest (~> 5.0)
|
|
18
|
+
rake (~> 12.0)
|
|
19
|
+
|
|
20
|
+
BUNDLED WITH
|
|
21
|
+
2.5.23
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ethan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Make a Calendar Toolkit
|
|
2
|
+
|
|
3
|
+
An offline Ruby toolkit for calendar grids, business scheduling, holiday dates, fiscal periods, date conversion, printable SVG/HTML, and iCalendar exports.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/makeacalendar/make-a-calendar-ruby/actions/workflows/ci.yml)
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [What it is](#what-it-is)
|
|
10
|
+
- [Install and start](#install-and-start)
|
|
11
|
+
- [Calendar grids and print output](#calendar-grids-and-print-output)
|
|
12
|
+
- [Business days and US federal holidays](#business-days-and-us-federal-holidays)
|
|
13
|
+
- [Pay and shift schedules](#pay-and-shift-schedules)
|
|
14
|
+
- [Retail fiscal calendars](#retail-fiscal-calendars)
|
|
15
|
+
- [Converters](#converters)
|
|
16
|
+
- [ICS export](#ics-export)
|
|
17
|
+
- [Command line](#command-line)
|
|
18
|
+
- [Rails use](#rails-use)
|
|
19
|
+
- [Date rules and limitations](#date-rules-and-limitations)
|
|
20
|
+
- [Development](#development)
|
|
21
|
+
- [Documentation and related tools](#documentation-and-related-tools)
|
|
22
|
+
- [Contributing, security, license](#contributing-security-license)
|
|
23
|
+
|
|
24
|
+
## What it is
|
|
25
|
+
|
|
26
|
+
Make a Calendar Toolkit packages reusable date and scheduling behavior for Ruby applications. It creates month and year grids, counts business days, applies a documented set of US federal holiday rules, builds pay and rotating-shift schedules, maps NRF-style 4-4-5/4-5-4/5-4-4 fiscal periods, converts common date representations, and exports calendars as SVG, print-oriented HTML, JSON, CSV, or date-only ICS.
|
|
27
|
+
|
|
28
|
+
Core features work offline using Ruby's standard library. The gem does not call the Make a Calendar website and does not reproduce its private implementation. Rails is not a runtime dependency.
|
|
29
|
+
|
|
30
|
+
The project was created by Ethan, the developer behind [Make a Calendar](https://make-a-calendar.com/), a browser-based calendar and date-tools platform.
|
|
31
|
+
|
|
32
|
+
## Install and start
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
gem install make_a_calendar_toolkit
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
require "date"
|
|
40
|
+
require "make_a_calendar"
|
|
41
|
+
|
|
42
|
+
calendar = MakeACalendar.month(year: 2027, month: 10, week_start: :monday)
|
|
43
|
+
puts calendar.to_json
|
|
44
|
+
File.write("october-2027.svg", calendar.to_svg(theme: :editorial, page_size: :letter))
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The library declares Ruby `>= 2.6` and has no runtime gem dependencies.
|
|
48
|
+
|
|
49
|
+
## Calendar grids and print output
|
|
50
|
+
|
|
51
|
+
Month grids contain four, five, or six rows unless `fixed_rows: 6` is requested. Cells carry civil `Date` values, adjacent-month information, weekdays, and ISO week data. A `Date` stays a date; no UTC instant is constructed to determine its weekday.
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
month = MakeACalendar.month(year: 2027, month: 10, week_start: :sunday, fixed_rows: 6)
|
|
55
|
+
puts month.to_csv
|
|
56
|
+
File.write("planner.html", month.to_html(theme: :ink_saver, page_size: :letter_landscape))
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Available print themes are `:editorial`, `:business`, `:academic`, and `:ink_saver`. Paper choices are `:letter`, `:a4`, `:letter_landscape`, and `:a4_landscape`. HTML includes print CSS; SVG is standalone and has accessible title and description elements. `MakeACalendar.year(year: 2027)` returns a twelve-month calendar suitable for one-page SVG or HTML output.
|
|
60
|
+
|
|
61
|
+
## Business days and US federal holidays
|
|
62
|
+
|
|
63
|
+
Date ranges include both endpoints by default. `inclusive: false` removes both endpoints. Saturday and Sunday are the default weekend (`Date#wday` values 6 and 0); pass your own weekend list for another work pattern. Adding a nonzero number of business days starts counting after the supplied date; zero returns that date unchanged.
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
holidays = MakeACalendar.federal_holidays(2027)
|
|
67
|
+
count = MakeACalendar.business_days_between(
|
|
68
|
+
Date.new(2027, 1, 1), Date.new(2027, 3, 31), holidays: holidays
|
|
69
|
+
)
|
|
70
|
+
deadline = MakeACalendar.add_business_days(Date.new(2027, 2, 1), 30, holidays: holidays)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Each federal `Holiday` keeps its legal date and observed weekday separately. The rule set includes effective-date distinctions for MLK Day, Juneteenth, the Monday holiday changes, and Veterans Day's 1971–1977 observance. It is a federal calendar reference, not state law, court rules, bank policy, or an employer's closure schedule. Add caller-owned holidays when a business uses different rules.
|
|
74
|
+
|
|
75
|
+
## Pay and shift schedules
|
|
76
|
+
|
|
77
|
+
`MakeACalendar::Scheduling.pay_dates` supports weekly, biweekly, semi-monthly, and monthly dates. Weekend/holiday adjustments must be selected explicitly with `:none`, `:following`, `:preceding`, or `:modified_following`. The library does not assume one employer's payday convention.
|
|
78
|
+
|
|
79
|
+
`shift_dates` accepts a repeating list such as `[2, 2, 3]` or `"2-2-3"`; entries alternate on-duty and off-duty blocks, beginning on duty. Results are date labels only and do not represent hours worked or a fixed-length UTC shift across daylight-saving changes.
|
|
80
|
+
|
|
81
|
+
## Retail fiscal calendars
|
|
82
|
+
|
|
83
|
+
`MakeACalendar.fiscal_calendar(year: 2029, pattern: :four_four_five)` uses the Sunday nearest February 1. The default label is the ending year, so a fiscal year labeled 2029 starts in 2028. `:four_four_five`, `:four_five_four`, and `:five_four_four` are supported. A 53rd week is assigned to period 12 by default; use `extra_week: :first_period` to assign it to period 1. This is one documented convention, not a claim that every company's accounting calendar matches it.
|
|
84
|
+
|
|
85
|
+
## Converters
|
|
86
|
+
|
|
87
|
+
`MakeACalendar::Converters` includes Unix seconds/milliseconds/microseconds/nanoseconds with rational arithmetic, Excel 1900 and 1904 serial dates, Windows FILETIME, ISO-8601 timestamps that require an explicit offset, and unambiguous `YYYY-DDD` / `YYYYDDD` ordinal dates. Excel 1900 serial 60 raises because it represents Excel's fictitious 1900-02-29. Two-digit ordinal years and historical Julian calendar conversions are not inferred.
|
|
88
|
+
|
|
89
|
+
## ICS export
|
|
90
|
+
|
|
91
|
+
`MakeACalendar.to_ics` exports date-only events with CRLF line endings, escaped text fields, folded content lines, stable UID defaults, and exclusive `DTEND` dates. It does not emit time-zone definitions or promise full recurrence-rule support.
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
ics = MakeACalendar.to_ics([
|
|
95
|
+
{ date: "2027-10-12", summary: "Planning day", description: "Quarterly review" }
|
|
96
|
+
])
|
|
97
|
+
File.write("planning.ics", ics)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Command line
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
make-calendar month --year 2027 --month 10 --format svg --output october.svg
|
|
104
|
+
make-calendar year --year 2027 --format html
|
|
105
|
+
make-calendar holidays --year 2027 --country us --observed
|
|
106
|
+
make-calendar business-days --from 2027-01-01 --to 2027-03-31 --observed
|
|
107
|
+
make-calendar add-business-days --date 2027-02-01 --days 30
|
|
108
|
+
make-calendar fiscal --year 2029 --pattern 445
|
|
109
|
+
make-calendar shifts --start 2027-01-01 --to 2027-01-31 --pattern 2-2-3
|
|
110
|
+
make-calendar convert excel --serial 45000 --system 1900
|
|
111
|
+
make-calendar convert unix --serial 1234567890 --system seconds
|
|
112
|
+
make-calendar export-ics --input events.json --output events.ics
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Output goes to standard output unless `--output` is supplied. Existing files are protected unless `--force` is used. Run `make-calendar --help` for the full syntax. The CLI accepts US holidays only in this release.
|
|
116
|
+
|
|
117
|
+
## Rails use
|
|
118
|
+
|
|
119
|
+
Rails is optional. In a Rails application, add the gem to the application's Gemfile, then call the Ruby API in a service object:
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
# app/services/monthly_report_calendar.rb
|
|
123
|
+
class MonthlyReportCalendar
|
|
124
|
+
def self.call(year:, month:)
|
|
125
|
+
MakeACalendar.month(year: year, month: month, week_start: :monday).to_svg
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
No Rails modules are loaded by the gem.
|
|
131
|
+
|
|
132
|
+
## Date rules and limitations
|
|
133
|
+
|
|
134
|
+
Gregorian civil dates are represented by Ruby `Date`. Month grids use Sunday-first or Monday-first ordering. ISO weeks and week-years follow Ruby's ISO calendar fields. The standard `Date` implementation defines the supported range; invalid dates and invalid month values raise errors. Holiday rules are limited to the documented US federal rule set; local and organization-specific holidays remain caller data. Payroll dates and fiscal-week policies are configurable where the library has a defined option. PDF/PNG generation, time-zone-aware timed events, state holidays, and astronomical/historic calendar systems are outside 0.1.0.
|
|
135
|
+
|
|
136
|
+
## Development
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
ruby -Ilib spec/all_spec.rb
|
|
140
|
+
find lib exe spec examples -name '*.rb' -print0 | xargs -0 -n1 ruby -c
|
|
141
|
+
gem build make_a_calendar_toolkit.gemspec
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
CI runs tests, Ruby syntax checks, package build, archive inspection, and CLI help on Ruby 2.7, 3.2, and 3.4. The test suite uses independent date expectations and covers calendar boundaries, holidays, business schedules, fiscal periods, converters, renderer escaping, ICS, and CLI behavior.
|
|
145
|
+
|
|
146
|
+
## Documentation and related tools
|
|
147
|
+
|
|
148
|
+
Technical guides are in [`docs/`](docs/). Helpful browser-based references include [monthly calendar templates](https://make-a-calendar.com/monthly-calendars), [date calculators](https://make-a-calendar.com/date-tools), [business-day calculator](https://make-a-calendar.com/business-days-calculator), [4-4-5 calendar overview](https://make-a-calendar.com/445-calendar), [date converters](https://make-a-calendar.com/converters), and the [iCalendar generator](https://make-a-calendar.com/ical-generator). Those pages are separate web tools; this gem runs locally and does not depend on them.
|
|
149
|
+
|
|
150
|
+
## Contributing, security, license
|
|
151
|
+
|
|
152
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md), [SECURITY.md](SECURITY.md), and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). Released under the [MIT License](LICENSE).
|
|
153
|
+
|
|
154
|
+
Created by Ethan, the developer behind [Make a Calendar](https://make-a-calendar.com/).
|
data/Rakefile
ADDED
data/SECURITY.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
Please report suspected vulnerabilities privately through GitHub's security advisory reporting for this repository. Include affected versions, impact, and a reproducible example when possible. Do not post credentials or sensitive personal information in a public issue.
|
|
4
|
+
|
|
5
|
+
The library has no network client and no runtime gem dependencies. Treat user-provided paths as application input, validate them before use, and do not render untrusted HTML outside the provided escaped calendar renderers.
|
data/docs/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
- [Getting started](getting-started.md)
|
|
4
|
+
- [Architecture](architecture.md)
|
|
5
|
+
- [API reference map](api-reference.md)
|
|
6
|
+
- [Date semantics](date-semantics.md)
|
|
7
|
+
- [Calendar rendering](calendar-rendering.md)
|
|
8
|
+
- [Printable calendars](printable-calendars.md)
|
|
9
|
+
- [Business-day arithmetic](business-days.md)
|
|
10
|
+
- [US federal holidays](holidays.md)
|
|
11
|
+
- [Pay and shift schedules](recurring-dates.md)
|
|
12
|
+
- [Fiscal 4-4-5 calendars](fiscal-445.md)
|
|
13
|
+
- [Date converters](date-converters.md)
|
|
14
|
+
- [iCalendar export](ics-export.md)
|
|
15
|
+
- [Rails integration](rails-integration.md)
|
|
16
|
+
- [Advanced examples](advanced-examples.md)
|
|
17
|
+
- [Related online resources](online-resources.md)
|
|
18
|
+
|
|
19
|
+
These guides document the behavior shipped in the gem. A dedicated documentation website is not configured in version 0.1.0; GitHub serves these source documents publicly.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Advanced examples
|
|
2
|
+
|
|
3
|
+
## Fiscal period lookup
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
fiscal = MakeACalendar.fiscal_calendar(year: 2029, pattern: :four_five_four)
|
|
7
|
+
period = fiscal.period_for(Date.new(2028, 10, 1))
|
|
8
|
+
puts [fiscal.label_year, period.quarter, period.number].join(" / ")
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Excel date validation
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
begin
|
|
15
|
+
date = MakeACalendar::Converters.excel(60, system: "1900")
|
|
16
|
+
rescue ArgumentError => error
|
|
17
|
+
warn error.message
|
|
18
|
+
end
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## iCalendar holiday export
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
events = MakeACalendar.federal_holidays(2027).map do |holiday|
|
|
25
|
+
{ date: holiday.observed_date, summary: holiday.name }
|
|
26
|
+
end
|
|
27
|
+
File.write("federal-holidays.ics", MakeACalendar.to_ics(events))
|
|
28
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# API reference map
|
|
2
|
+
|
|
3
|
+
Require `make_a_calendar`.
|
|
4
|
+
|
|
5
|
+
- `MakeACalendar.month`, `MakeACalendar.year`
|
|
6
|
+
- `MakeACalendar.business_days_between`, `MakeACalendar.add_business_days`
|
|
7
|
+
- `MakeACalendar.federal_holidays`, `MakeACalendar.fiscal_calendar`, `MakeACalendar.to_ics`
|
|
8
|
+
- `MakeACalendar::DateMath` for date grids, quarters, date ranges, ordinals, and ISO weeks
|
|
9
|
+
- `MakeACalendar::BusinessDays` for iteration and month/year totals
|
|
10
|
+
- `MakeACalendar::Scheduling` for pay dates and shift cycles
|
|
11
|
+
- `MakeACalendar::Converters` for Unix, Excel, FILETIME, ISO 8601, and ordinal values
|
|
12
|
+
- `Calendar#to_json`, `#to_csv`, `#to_html`, and `#to_svg`
|
|
13
|
+
- `YearCalendar#to_json`, `#to_html`, and `#to_svg`
|
|
14
|
+
|
|
15
|
+
See the README and focused guides for boundary conventions and examples.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
The `DateMath` module owns civil date operations and month-grid geometry. Calendar renderers consume immutable grids. Scheduling modules implement holiday rules, workday iteration, pay dates, rotating patterns, and NRF-style fiscal periods. Converter methods make source epochs and units explicit. The `ICS` module serializes date-only events. The executable maps options to these public modules and does not contain a separate date engine.
|
|
4
|
+
|
|
5
|
+
The gem uses the Ruby standard library (`date`, `time`, `json`, `csv`, `cgi`, and `optparse`) and no runtime dependencies. It does not request data from Make a Calendar or claim to reproduce the site's private code.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Business-day arithmetic
|
|
2
|
+
|
|
3
|
+
Use `MakeACalendar.business_days_between(from, to, weekend: [0, 6], holidays: [], inclusive: true)` to count working dates. Ruby weekday numbers are Sunday 0 through Saturday 6. A `Holiday` contributes its observed date; a `Date` or ISO date string contributes itself.
|
|
4
|
+
|
|
5
|
+
`MakeACalendar.add_business_days(date, count, ...)` counts after the start for nonzero values. `BusinessDays.each_workday` yields dates in the requested range. `in_month` and `in_year` count weekdays with the same options.
|
|
6
|
+
|
|
7
|
+
The US federal holiday rules are convenience inputs. Add caller-owned dates for company closures and verify contract, court, payroll, and state rules independently.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Calendar rendering
|
|
2
|
+
|
|
3
|
+
`Calendar#to_svg` returns a standalone SVG with a title, description, legible day cells, and an optional holiday label. `Calendar#to_html` returns a document with print CSS. Both escape user-facing text and offer `:editorial`, `:business`, `:academic`, and `:ink_saver` themes. Paper dimensions accept Letter or A4 in portrait or landscape orientation.
|
|
4
|
+
|
|
5
|
+
The yearly renderer lays out 12 month grids on one page. PDF and raster exports are not included; print HTML through a browser or convert SVG with an application chosen by the caller.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Date converters
|
|
2
|
+
|
|
3
|
+
`Converters.unix` takes a value and explicit unit (`:seconds`, `:milliseconds`, `:microseconds`, or `:nanoseconds`) and returns UTC `Time`. `Converters.to_unix` reverses the conversion.
|
|
4
|
+
|
|
5
|
+
`Converters.excel` accepts the 1900 or 1904 system; 1900 serial 60 is rejected. Fractional days return a UTC `Time`. `Converters.filetime` and `to_filetime` convert 100-nanosecond ticks since 1601-01-01 UTC. `parse_time` requires an explicit UTC marker or numeric offset. `ordinal` accepts only four-digit-year formats `YYYY-DDD` and `YYYYDDD`.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Date semantics
|
|
2
|
+
|
|
3
|
+
## Civil dates
|
|
4
|
+
|
|
5
|
+
Pass a `Date` or ISO `YYYY-MM-DD` string to date-only APIs. A civil date has no time zone; its weekday is calculated directly as a calendar date.
|
|
6
|
+
|
|
7
|
+
## Month grids
|
|
8
|
+
|
|
9
|
+
Week starts are `:sunday` (Ruby `Date#wday` 0) or `:monday`. Natural grids use four through six rows. `fixed_rows: 6` creates a consistent print height. Cells outside the month carry adjacent dates. ISO week number and week-year are attached per cell.
|
|
10
|
+
|
|
11
|
+
## Business-day ranges
|
|
12
|
+
|
|
13
|
+
`BusinessDays.between` includes both endpoints by default, skips the configured weekend, and excludes the supplied holiday date or each holiday's `observed_date`. Set `inclusive: false` to exclude both range endpoints. Adding a nonzero number of workdays moves forward or backward after the start date.
|
|
14
|
+
|
|
15
|
+
## Holiday history
|
|
16
|
+
|
|
17
|
+
US federal rules distinguish actual dates from weekend-observed dates. Monday observances reflect the post-1971 Uniform Monday Holiday rules; Veterans Day's 1971–1977 Monday observance is accounted for. Juneteenth begins in 2021. Federal observance is not a proxy for state law, financial market closures, or a company's policy.
|
|
18
|
+
|
|
19
|
+
## Timestamp conversion
|
|
20
|
+
|
|
21
|
+
Timestamp functions require an explicit unit. ISO timestamps require a UTC marker or numeric offset. Excel's 1900 system rejects serial 60, and FILETIME uses 100-nanosecond ticks since 1601-01-01 UTC.
|
data/docs/fiscal-445.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Retail 4-4-5 fiscal calendars
|
|
2
|
+
|
|
3
|
+
The retail calendar starts on the Sunday nearest February 1. By default, the year label is the ending year: a calendar labeled 2029 begins at the anchor Sunday nearest February 1, 2028.
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
fiscal = MakeACalendar.fiscal_calendar(year: 2029, pattern: :four_four_five)
|
|
7
|
+
puts fiscal.to_h
|
|
8
|
+
puts fiscal.period_for(Date.new(2029, 1, 10)).number
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The 12 periods repeat the selected 4-4-5, 4-5-4, or 5-4-4 week sequence. A 53rd week goes to period 12 unless `extra_week: :first_period` is selected. Organizations can use different fiscal anchors or adjustment policies; this implementation does not claim universal accounting compatibility.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Getting started
|
|
2
|
+
|
|
3
|
+
Install `make_a_calendar_toolkit`, require `make_a_calendar`, and call the same API from scripts, services, or Rails applications. Runtime code has no external gem dependencies and performs no network requests.
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
require "make_a_calendar"
|
|
7
|
+
|
|
8
|
+
calendar = MakeACalendar.month(year: 2027, month: 10, week_start: :monday)
|
|
9
|
+
File.write("october.svg", calendar.to_svg)
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
For command-line use, install the gem then run `make-calendar --help`. By default, commands print to standard output; `--output FILE` writes a file and refuses to overwrite it unless `--force` is given.
|
data/docs/holidays.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# US federal holiday dates
|
|
2
|
+
|
|
3
|
+
`MakeACalendar.federal_holidays(year)` returns `Holiday` entries with a legal date and a weekend-observed date. The model covers federal holidays in the modern statutory era and distinguishes important changes: Memorial Day's pre-1971 May 30 date, Washington's Birthday's pre-1971 February 22 date, Columbus Day from 1971, Veterans Day's 1971–1977 October observance, Juneteenth from 2021, and Thanksgiving's 1939 move to the fourth Thursday.
|
|
4
|
+
|
|
5
|
+
The older Thanksgiving dates use a recurring November rule as a practical calendar approximation; Presidential proclamations varied in some early years. This is not an authoritative legal history or a state, bank, or employer closure calendar. Supply custom `Date` values or `Holiday` objects when a caller follows other rules.
|
|
6
|
+
|
|
7
|
+
For a range spanning year boundaries, `Holidays.observed_dates(first_year, last_year)` includes adjacent legal years so a New Year's observed date on December 31 is available.
|
data/docs/ics-export.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# iCalendar export
|
|
2
|
+
|
|
3
|
+
`MakeACalendar.to_ics(events, name: ...)` writes date-only VEVENT entries with a one-day exclusive `DTEND`. It escapes text fields, folds lines at the RFC 5545 octet limit, and writes CRLF separators. UIDs are deterministic for an ordered input list unless an event supplies one. `DTSTAMP` records the export time.
|
|
4
|
+
|
|
5
|
+
This subset omits `VTIMEZONE`, timed events, and recurrence rules. Use it for all-day planning data, not for local-time meeting schedules where daylight-saving behavior matters.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Online calendar resources
|
|
2
|
+
|
|
3
|
+
This gem is an offline Ruby library. For interactive browser workflows, the creator also maintains [Make a Calendar](https://make-a-calendar.com/).
|
|
4
|
+
|
|
5
|
+
- [Monthly calendars](https://make-a-calendar.com/monthly-calendars) provides customizable month pages and printable layouts.
|
|
6
|
+
- [Date tools](https://make-a-calendar.com/date-tools) groups business-day, pay-period, shift, and fiscal calculators.
|
|
7
|
+
- [Business-day calculator](https://make-a-calendar.com/business-days-calculator) counts weekdays with observed US federal holidays.
|
|
8
|
+
- [4-4-5 calendar](https://make-a-calendar.com/445-calendar) documents the site's retail calendar generator.
|
|
9
|
+
- [Date converters](https://make-a-calendar.com/converters) covers timestamp and spreadsheet formats.
|
|
10
|
+
- [iCalendar generator](https://make-a-calendar.com/ical-generator) builds all-day calendar files in the browser.
|
|
11
|
+
|
|
12
|
+
These links are contextual resources; the Ruby toolkit uses its own original implementation and does not access the website.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Payroll schedules
|
|
2
|
+
|
|
3
|
+
`Scheduling.pay_dates` supports weekly and biweekly anchors plus semi-monthly and monthly schedules. Semi-monthly defaults to the 15th and the month's last day. Monthly schedules use the anchor's day and clamp to the last day in shorter months.
|
|
4
|
+
|
|
5
|
+
Choose a non-working-day adjustment explicitly: `:none`, `:following`, `:preceding`, or `:modified_following`. Pass weekend dates and holiday dates as appropriate to the organization. No adjustment should be assumed to match every payroll contract.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Printable calendars
|
|
2
|
+
|
|
3
|
+
Monthly SVG output uses a fixed page viewBox and scalable geometry. HTML output adds print CSS for A4/Letter paper in portrait or landscape. The `:ink_saver` theme uses a white background and dark lines; `:editorial`, `:business`, and `:academic` adjust the color palette. No remote fonts, logos, or tracking are added.
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
calendar = MakeACalendar.month(year: 2027, month: 10, week_start: :monday, fixed_rows: 6)
|
|
7
|
+
File.write("planner.svg", calendar.to_svg(theme: :ink_saver, page_size: :a4_landscape))
|
|
8
|
+
File.write("planner.html", calendar.to_html(theme: :business, page_size: :letter))
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
SVG and HTML are provided; PDF and PNG are not. Print the HTML in a browser or use an external converter selected by your application.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Pay dates and shift rotations
|
|
2
|
+
|
|
3
|
+
`Scheduling.pay_dates` creates weekly, biweekly, semi-monthly, or monthly dates. Weekly schedules use a seven-day anchor interval; biweekly uses fourteen days. Semi-monthly dates default to the 15th and month end. Monthly dates preserve the anchor's day and clamp to the last day in shorter months. The caller chooses weekend/holiday handling.
|
|
4
|
+
|
|
5
|
+
`Scheduling.shift_dates` accepts alternating on/off block lengths. `"2-2-3"` means two on, two off, three on, then the cycle repeats. An anchor date establishes cycle day 1. The library returns civil dates and does not infer shift duration, timezone, or daylight-saving behavior.
|
|
6
|
+
|
|
7
|
+
Generated date ranges are limited to 100 years to keep accidental oversized requests bounded.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Repeat a 2-on, 2-off, 3-on rotation over January 2027.
|
|
2
|
+
require "make_a_calendar"
|
|
3
|
+
rows = MakeACalendar::Scheduling.shift_dates(start_date: "2027-01-01", end_date: "2027-01-31", pattern: "2-2-3", anchor: "2027-01-01")
|
|
4
|
+
puts rows.select { |row| row[:on_duty] }.map { |row| row[:date].iso8601 }
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Export 2027 observed federal holidays as date-only iCalendar events.
|
|
2
|
+
require "make_a_calendar"
|
|
3
|
+
events = MakeACalendar.federal_holidays(2027).map { |holiday| { date: holiday.observed_date, summary: holiday.name } }
|
|
4
|
+
print MakeACalendar.to_ics(events, name: "US Federal Holidays 2027")
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# A service object for a Rails app; Rails itself is not required to run this example.
|
|
2
|
+
require "make_a_calendar"
|
|
3
|
+
class MonthlyCalendarService
|
|
4
|
+
def self.call(year:, month:)
|
|
5
|
+
MakeACalendar.month(year: year, month: month, week_start: :monday).to_html(theme: :business)
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
puts MonthlyCalendarService.call(year: 2027, month: 10).include?("<table>")
|