🗓️ Fasti
A flexible calendar application with multi-country holiday support, written in Ruby. Fasti provides beautiful, colorful calendar displays with support for multiple output formats, configurable week start days, and country-specific holiday highlighting.
Features
- Multiple Display Formats: Month, quarter (3 months), and full year views
- Configurable Week Start: Start weeks on any day of the week
- Holiday Support: Country-specific holiday highlighting using the holidays gem
- Historical Calendar Transitions: Julian to Gregorian calendar transitions with country-specific gap handling
- Color Coding: ANSI color support for holidays, weekends, and today's date
- 
Configuration File: XDG-compliant Ruby-based configuration file support (~/.config/fasti/config.rb)
- 
Locale Detection: Automatic country detection from LC_ALLandLANGenvironment variables
- Command Line Interface: Full-featured CLI with comprehensive options
Installation
Install the gem by executing:
gem install fastiOr add it to your Gemfile:
gem 'fasti'Then execute:
bundle installUsage
Basic Usage
Display the current month:
fastiDisplay a specific month and year:
fasti 6 2024Display Formats
Month View (default):
fasti 6 2024 --format month
# Or using shortcuts:
fasti 6 2024 --month
fasti 6 2024 -mQuarter View (3 months side by side):
fasti 6 2024 --format quarter
# Or using shortcuts:
fasti 6 2024 --quarter
fasti 6 2024 -qYear View (all 12 months):
fasti 2024 --format year
# Or using shortcuts:
fasti 2024 --year
fasti 2024 -yWeek Start Configuration
You can start the week on any day of the week:
fasti --start-of-week sunday     # Default
fasti --start-of-week monday     # Common international standard
fasti --start-of-week tuesday
fasti --start-of-week wednesday
fasti --start-of-week thursday
fasti --start-of-week friday
fasti --start-of-week saturdayCountry and Holiday Support
Specify country for holiday highlighting:
fasti --country JP    # Japan
fasti --country US    # United States
fasti --country GB    # United Kingdom
fasti --country DE    # GermanyFasti automatically detects your country from environment variables (LC_ALL, LANG), but you can override this with the --country option.
Historical Calendar Transitions
For historical dates, Fasti supports country-specific Julian to Gregorian calendar transitions with proper gap handling:
# Show October 1582 (Italian transition) - compressed display
fasti 10 1582 --country IT
# British transition - September 3-13, 1752 never existed in Britain
fasti 9 1752 --country GB
# Asian countries transitioned from lunisolar calendars
# Japan transitioned in 1873 (Meiji era)
fasti 12 1872 --country JP
# Korea transitioned in 1896 (Korean Empire era)
fasti 12 1895 --country KR
# France had different transition date than Italy
fasti 12 1582 --country FR
# Sweden's complex transition in 1753
fasti 3 1753 --country SECalendar transitions are displayed in compressed format (like UNIX cal command) for continuous display without confusing gaps.
Supported countries with calendar transition dates:
Early Catholic adoption (1582-1583):
- Italy, Spain, Portugal (1582-10-15)
- France (1582-12-20)
- Belgium/Spanish Netherlands (1583-01-06)
Protestant countries (1700-1753):
- Netherlands (1700-07-12), Switzerland (1700-01-23), Denmark/Norway (1700-03-01)
- Great Britain & colonies: US, Canada, Australia, etc. (1752-09-14)
- Sweden (1753-03-01)
Eastern Europe (1916-1927):
- Bulgaria (1916), Russia (1918), Romania/Yugoslavia (1919), Greece (1923), Turkey (1927)
Asian countries (1873-1967):
- Japan (1873), China/Taiwan (1912), Korea (1896), Vietnam (1967), Thailand (1888)
Note: Asian countries transitioned from lunisolar calendars to Gregorian; pre-transition dates use proleptic Gregorian calendar for computational consistency.
Command Line Options
Usage: fasti [month] [year] [options]
Arguments:
  month  Month (1-12, optional)
  year   Year (optional)
Format options:
  -f, --format FORMAT           Output format (month, quarter, year)
  -m, --month                   Display month format (equivalent to --format month)
  -q, --quarter                 Display quarter format (equivalent to --format quarter)
  -y, --year                    Display year format (equivalent to --format year)
Calendar display options:
  -w, --start-of-week WEEKDAY   Week start day (any day of the week)
  -c, --country COUNTRY         Country code for holidays (e.g., JP, US, GB, DE)
  -s, --style STYLE             Custom styling (e.g., "sunday:bold holiday:foreground=red today:inverse")
Other options:
  -v, --version                 Show version
  -h, --help                    Show this help
Positional Arguments
No arguments - Display current month:
fastiOne argument - Interpreted based on value:
- 1-12: Month for current year
- 13+: Year for current month
fasti 6        # June current year
fasti 2024     # Current month 2024Two arguments - Month and year:
fasti 6 2024   # June 2024Configuration File
Create a configuration file at ~/.config/fasti/config.rb (or $XDG_CONFIG_HOME/fasti/config.rb) using Ruby syntax to set default options:
# Example configuration
Fasti.configure do |config|
  config.format = :quarter
  config.start_of_week = :monday
  config.country = :US
  # Custom styling (optional)
  config.style = {
    sunday: { bold: true },
    holiday: { foreground: :red, bold: true },
    today: { inverse: true }
  }
endSee examples/config.rb for a complete configuration example.
Command line options override configuration file settings.
Styling
By default, Fasti displays all days with normal text styling. You can customize the appearance of different day types using the style configuration option:
- sunday: Configurable styling for Sundays
- holiday: Configurable styling for holidays
- today: Configurable styling for today's date
- monday, tuesday, etc.: Configurable styling for individual weekdays
You can apply styling using the --style option with space-separated target:attribute pairs:
# Bold Sundays and red holidays
fasti --style "sunday:bold holiday:foreground=red"
# Multiple attributes for the same target
fasti --style "today:bold,inverse sunday:foreground=blue"
# Mix different styling attributes
fasti --style "sunday:bold holiday:foreground=red,background=yellow today:inverse"
# Override config file settings with no- prefix (boolean attributes only)
fasti --style "sunday:no-bold,no-italic holiday:foreground=red"  # Remove boolean stylingExamples
Display current month with Monday start:
fasti --start-of-week mondayDisplay current month with Wednesday start:
fasti --start-of-week wednesdayShow quarter view for summer 2024 in Japan:
fasti 7 2024 --format quarter --country JPFull year 2024 with US holidays:
fasti 2024 --format year --country USEnvironment Variables
Fasti respects the following environment variables for automatic country detection:
- 
LC_ALL(highest priority)
- 
LANG(fallback)
Note: Only LC_ALL and LANG are used for country detection. Other LC_* variables (such as LC_MESSAGES, LC_TIME) are not used as they represent specific locale categories rather than the user's preferred country for holiday context.
Example:
export LANG=ja_JP.UTF-8  # Automatically uses Japan (JP) holidays
fastiDevelopment
After checking out the repo, run bin/setup to install dependencies:
git clone https://github.com/sakuro/fasti.git
cd fasti
bin/setupRun the tests (includes coverage measurement):
bundle exec rake specRun linting:
bundle exec rake rubocopGenerate API documentation:
bundle exec rake docClean temporary files:
bundle exec rake cleanRemove all generated files:
bundle exec rake clobberRun all checks:
bundle exec rakeTo install this gem onto your local machine:
bundle exec rake installFor an interactive prompt that allows you to experiment:
bin/consoleDependencies
- dry-configurable (~> 1.0): Configuration management
- dry-schema (~> 1.13): Configuration validation
- dry-types (~> 1.7): Type system for configuration
- holidays (~> 8.0): Country-specific holiday data
- locale (~> 2.1): Locale parsing for country detection
- tint_me (~> 1.0): ANSI color support
- zeitwerk (~> 2.6): Code autoloading
Development Dependencies
- rspec (~> 3.0): Testing framework
- rubocop (~> 1.21): Code linting
- simplecov (~> 0.22): Code coverage measurement
- yard (from GitHub): API documentation generation with Data class support
Releasing
This project uses automated GitHub Actions workflows for releases. Maintainers can create new releases with a simple workflow execution.
Quick Release Process
- Go to Actions → Release Preparation → Run workflow
- Enter version number (e.g., 1.0.0)
- Review and merge the generated PR
- Release is automatically published to RubyGems and GitHub
For detailed instructions, troubleshooting, and setup requirements, see RELEASING.md.
Known Limitations
Historical Calendar Support
Fasti properly handles historical calendar transitions with country-specific transition dates. Each country switched from Julian to Gregorian calendar at different times, and these transition periods contain non-existent dates that are handled correctly.
Historical transition periods display correctly with proper gap handling:
# Italian transition works correctly - shows compressed display
fasti 10 1582 --country IT
# Asian countries show transitions from lunisolar calendars
fasti 12 1872 --country JPNote: Standard UNIX calendar tools like cal and gcal correctly handle these historical transitions by appropriately skipping non-existent dates during calendar reforms.
Technical Details: Fasti uses country-specific Julian to Gregorian calendar transition dates with proper gap handling. Ruby's Date class uses Italy's transition date (Date::ITALY) by default, but Fasti's CalendarTransition class supports transitions for different countries, properly handling non-existent dates during calendar reforms.
Available Countries: Fasti supports 25+ countries with calendar transitions:
- Catholic countries: Italy/Spain/Portugal (1582), France (1582), Belgium (1583)
- Protestant countries: Netherlands (1700), Switzerland (1700), Denmark/Norway (1700), Great Britain & colonies (1752), Sweden (1753)
- Eastern Europe: Bulgaria (1916), Russia (1918), Romania/Yugoslavia (1919), Greece (1923), Turkey (1927)
- Asian countries: Japan (1873), China/Taiwan (1912), Korea (1896), Vietnam (1967), Thailand (1888)
Asian countries used lunisolar calendars before adoption; pre-transition dates use proleptic Gregorian calendar for computational consistency.
FAQ
Why is it called "fasti"?
The name comes from the Latin fasti, meaning "calendar" or "list of days". Roman fasti were official calendars that recorded important dates, festivals, and holidays - much like what this application does for modern users.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/sakuro/fasti.
- Fork the repository
- Create your feature branch (git checkout -b my-new-feature)
- Write tests for your changes
- Ensure all tests pass (bundle exec rake spec)
- Ensure code passes linting (bundle exec rake rubocop)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create a Pull Request
License
The gem is available as open source under the terms of the MIT License.