zmanim 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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +6 -0
  5. data/LICENSE +504 -0
  6. data/README.md +124 -0
  7. data/Rakefile +2 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/lib/zmanim.rb +6 -0
  11. data/lib/zmanim/astronomical_calendar.rb +105 -0
  12. data/lib/zmanim/hebrew_calendar/hebrew_date_formatter.rb +243 -0
  13. data/lib/zmanim/hebrew_calendar/jewish_calendar.rb +390 -0
  14. data/lib/zmanim/hebrew_calendar/jewish_date.rb +397 -0
  15. data/lib/zmanim/limudim/anchor/day_of_month_anchor.rb +49 -0
  16. data/lib/zmanim/limudim/anchor/day_of_week_anchor.rb +26 -0
  17. data/lib/zmanim/limudim/anchor/day_of_year_anchor.rb +27 -0
  18. data/lib/zmanim/limudim/calculators/daf_yomi_bavli.rb +53 -0
  19. data/lib/zmanim/limudim/calculators/daf_yomi_yerushalmi.rb +58 -0
  20. data/lib/zmanim/limudim/calculators/mishna_yomis.rb +48 -0
  21. data/lib/zmanim/limudim/calculators/parsha.rb +91 -0
  22. data/lib/zmanim/limudim/calculators/tehillim_monthly.rb +43 -0
  23. data/lib/zmanim/limudim/cycle.rb +40 -0
  24. data/lib/zmanim/limudim/interval.rb +37 -0
  25. data/lib/zmanim/limudim/limud.rb +42 -0
  26. data/lib/zmanim/limudim/limud_calculator.rb +137 -0
  27. data/lib/zmanim/limudim/limudim_formatter.rb +168 -0
  28. data/lib/zmanim/limudim/unit.rb +53 -0
  29. data/lib/zmanim/util/astronomical_calculations.rb +34 -0
  30. data/lib/zmanim/util/geo_location.rb +116 -0
  31. data/lib/zmanim/util/hebrew_numeric_formatter.rb +67 -0
  32. data/lib/zmanim/util/math_helper.rb +14 -0
  33. data/lib/zmanim/util/noaa_calculator.rb +180 -0
  34. data/lib/zmanim/util/sun_times_calculator.rb +123 -0
  35. data/lib/zmanim/util/text_helper.rb +7 -0
  36. data/lib/zmanim/util/time_zone_converter.rb +20 -0
  37. data/lib/zmanim/version.rb +3 -0
  38. data/lib/zmanim/zmanim_calendar.rb +106 -0
  39. data/zmanim.gemspec +37 -0
  40. metadata +153 -0
@@ -0,0 +1,124 @@
1
+ # Zmanim
2
+
3
+ A Ruby library for Zmanim.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'zmanim'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install zmanim
20
+
21
+ ## Usage
22
+
23
+ Some common examples include...
24
+
25
+ #### Zmanim calculations
26
+
27
+ ```ruby
28
+
29
+ # Initialize a new ZmanimCalendar object, defaults to using today's date in GMT, located at Greenwich, England
30
+ zmanim = Zmanim::ZmanimCalendar.new
31
+ #=> #<Zmanim::ZmanimCalendar:0x007fa73c2ec7d8 @geo_location=#<Zmanim::Util::GeoLocation:0x007fa73c2ec710 @location_name="Greenwich, England", @latitude=51.4772, @longitude=0, @time_zone=#<TZInfo::DataTimezone: GMT>, @elevation=0>, @date=#<Date: 2018-01-09 ((2458128j,0s,0n),+0s,2299161j)>, @astronomical_calculator=#<Zmanim::Util::NOAACalculator:0x007fa73c24e920>, @candle_lighting_offset=18>
32
+
33
+ # Calculate the sunset for today at that location
34
+ zmanim.sunset
35
+ #=> #<DateTime: 2018-01-08T16:10:12+00:00 ((2458127j,58212s,336684777n),+0s,2299161j)>
36
+
37
+ # Prepare a new location
38
+ location = Zmanim::Util::GeoLocation.new('Lakewood, NJ', 40.0721087, -74.2400243, 'US/Eastern', elevation: 15)
39
+ #=> #<Zmanim::Util::GeoLocation:0x007fa73c1c5008 @location_name="Lakewood, NJ", @latitude=40.0721087, @longitude=-74.2400243, @time_zone=#<TZInfo::DataTimezone: US/Eastern>, @elevation=15>
40
+
41
+ # Initialize a new ZmanimCalendar object, passing a specific location and date
42
+ zmanim = Zmanim::ZmanimCalendar.new(geo_location: location, date: Date.parse('2017-12-15'))
43
+ #=> #<Zmanim::ZmanimCalendar:0x007fa73c33ee98 @geo_location=#<Zmanim::Util::GeoLocation:0x007fa73c1c5008 @location_name="Lakewood, NJ", @latitude=40.0721087, @longitude=-74.2400243, @time_zone=#<TZInfo::DataTimezone: US/Eastern>, @elevation=15>, @date=#<Date: 2017-12-15 ((2458103j,0s,0n),+0s,2299161j)>, @astronomical_calculator=#<Zmanim::Util::NOAACalculator:0x007fa73c33ee48>, @candle_lighting_offset=18>
44
+
45
+ # Calculate Sof Zman Krias Shma for that location/date per the opinion of GR"A
46
+ zmanim.sof_zman_shma_gra
47
+ #=> #<DateTime: 2017-12-15T09:32:09-05:00 ((2458103j,52329s,383390214n),-18000s,2299161j)>
48
+ ```
49
+
50
+ #### Date Calculations
51
+
52
+ ```ruby
53
+ # Initialize a new JewishDate object with today's date
54
+ date = Zmanim::HebrewCalendar::JewishDate.new
55
+ # => #<Zmanim::HebrewCalendar::JewishDate:0x007fa73c2976e8 @gregorian_date=#<Date: 2018-01-09 ((2458128j,0s,0n),+0s,-Infj)>, @absolute_date=736703, @day_of_week=3, @molad_chalakim=0, @molad_minutes=0, @molad_hours=0, @jewish_year=5778, @jewish_month=10, @jewish_day=22>
56
+
57
+ # Initialize a HebrewDateFormatter object
58
+ formatter = Zmanim::HebrewCalendar::HebrewDateFormatter.new
59
+ #=> #<Zmanim::HebrewCalendar::HebrewDateFormatter:0x007fa73c2ec558 ...>
60
+
61
+ # Format the jewish date
62
+ formatter.format(date)
63
+ #=> "22 Teves, 5778"
64
+
65
+ # Change the formatter to use hebrew
66
+ formatter.hebrew_format = true
67
+ formatter.format(date)
68
+ #=> "כ״ב טבת תשע״ח"
69
+ ```
70
+
71
+ #### Jewish Calendar occasions
72
+
73
+ ```ruby
74
+ # Initialize a new JewishCalendar object with a specific Jewish date
75
+ calendar = Zmanim::HebrewCalendar::JewishCalendar.new(5778, 7, 4)
76
+ # => #<Zmanim::HebrewCalendar::JewishCalendar:0x007fa73c256ad0 @gregorian_date=#<Date: 2017-09-24 ((2458021j,0s,0n),+0s,-Infj)>, @absolute_date=736596, @day_of_week=1, @molad_chalakim=0, @molad_minutes=0, @molad_hours=0, @jewish_year=5778, @jewish_month=7, @jewish_day=4, @in_israel=false, @use_modern_holidays=false>
77
+
78
+ formatter = Zmanim::HebrewCalendar::HebrewDateFormatter.new
79
+
80
+ # Format the name of a significant day
81
+ formatter.format_significant_day(calendar)
82
+ #=> "Fast of Gedalyah"
83
+
84
+ # Format the name of a significant shabbos
85
+ calendar.set_jewish_date(5778, 7, 3)
86
+ formatter.format_significant_shabbos(calendar)
87
+ #=> "Shabbos Shuva"
88
+ ```
89
+
90
+ #### Learning cycles
91
+
92
+ ```ruby
93
+ # Fetch the daf for a calendar day
94
+ daf = calendar.daf_yomi_bavli
95
+ #=> #<Zmanim::Limudim::Limud:0x007fa73c1c7c40 ...>
96
+ daf.description
97
+ #=> "sanhedrin 69"
98
+
99
+ # Format the daf
100
+ limud_formatter = Zmanim::Limudim::LimudimFormatter.new
101
+ limud_formatter.hebrew_format = true
102
+ limud_formatter.format_talmudic(daf)
103
+ #=> "סנהדרין סט"
104
+
105
+ # Format the parsha of the week
106
+ parsha = calendar.parshas_hashavua
107
+ limud_formatter.format_parsha(parsha)
108
+ #=> "פרשת האזינו"
109
+ ```
110
+
111
+ There is much more functionality included than demonstrated here. Feel free to experiment or read the source code to learn more!
112
+
113
+ ---
114
+ ## Development
115
+
116
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
117
+
118
+ ## Contributing
119
+
120
+ Bug reports and pull requests are welcome on GitHub at https://github.com/pinnymz/ruby-zmanim. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
121
+
122
+ ## Code of Conduct
123
+
124
+ Everyone interacting in the Zmanim project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/pinnymz/ruby-zmanim/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "zmanim"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,6 @@
1
+ require 'tzinfo'
2
+ Dir[File.dirname(__FILE__) + "/**/*.rb"].each {|file| require file }
3
+
4
+ module Zmanim
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,105 @@
1
+ module Zmanim
2
+ class AstronomicalCalendar
3
+ attr_accessor :geo_location,
4
+ :astronomical_calculator,
5
+ :date
6
+
7
+ GEOMETRIC_ZENITH = 90
8
+ CIVIL_ZENITH = 96
9
+ NAUTICAL_ZENITH = 102
10
+ ASTRONOMICAL_ZENITH = 108
11
+
12
+ MINUTE_MILLIS = 60 * 1000
13
+ HOUR_MILLIS = MINUTE_MILLIS * 60
14
+
15
+ def initialize(opts={})
16
+ @geo_location = opts[:geo_location] || Util::GeoLocation.GMT
17
+ @date = opts[:date] || Date.today
18
+ @astronomical_calculator = opts[:calculator] || Util::NOAACalculator.new
19
+ end
20
+
21
+ def sunrise
22
+ date_time_from_time_of_day utc_sunrise(GEOMETRIC_ZENITH), :sunrise
23
+ end
24
+
25
+ def sea_level_sunrise
26
+ sunrise_offset_by_degrees(GEOMETRIC_ZENITH)
27
+ end
28
+
29
+ def sunrise_offset_by_degrees(offset_zenith)
30
+ date_time_from_time_of_day utc_sea_level_sunrise(offset_zenith), :sunrise
31
+ end
32
+
33
+ def sunset
34
+ date_time_from_time_of_day utc_sunset(GEOMETRIC_ZENITH), :sunset
35
+ end
36
+
37
+ def sea_level_sunset
38
+ sunset_offset_by_degrees(GEOMETRIC_ZENITH)
39
+ end
40
+
41
+ def sunset_offset_by_degrees(offset_zenith)
42
+ date_time_from_time_of_day utc_sea_level_sunset(offset_zenith), :sunset
43
+ end
44
+
45
+ def utc_sunrise(zenith)
46
+ astronomical_calculator.utc_sunrise(adjusted_date, geo_location, zenith, adjust_for_elevation: true)
47
+ end
48
+
49
+ def utc_sunset(zenith)
50
+ astronomical_calculator.utc_sunset(adjusted_date, geo_location, zenith, adjust_for_elevation: true)
51
+ end
52
+
53
+ def utc_sea_level_sunrise(zenith)
54
+ astronomical_calculator.utc_sunrise(adjusted_date, geo_location, zenith, adjust_for_elevation: false)
55
+ end
56
+
57
+ def utc_sea_level_sunset(zenith)
58
+ astronomical_calculator.utc_sunset(adjusted_date, geo_location, zenith, adjust_for_elevation: false)
59
+ end
60
+
61
+ def temporal_hour(sunrise=sea_level_sunrise, sunset=sea_level_sunset)
62
+ return unless sunset && sunrise
63
+ daytime_hours = ((sunset - sunrise) * 24).to_f
64
+ (daytime_hours / 12) * HOUR_MILLIS
65
+ end
66
+
67
+ def sun_transit
68
+ sunrise = sea_level_sunrise
69
+ sunset = sea_level_sunset
70
+ return unless sunrise && sunset
71
+ noon_hour = (temporal_hour(sunrise, sunset) / HOUR_MILLIS) * 6.0
72
+ sunrise + (noon_hour / 24.0)
73
+ end
74
+
75
+ private
76
+
77
+ def adjusted_date
78
+ date + geo_location.antimeridian_adjustment
79
+ end
80
+
81
+ # returns DateTime adjusted for the provided Time Zone
82
+ def date_time_from_time_of_day(time_of_day, mode)
83
+ return unless time_of_day
84
+ hours, remainder = (time_of_day * 3600).divmod 3600
85
+ minutes, seconds = remainder.divmod 60
86
+ year, month, day = %i(year month day).map(&adjusted_date.method(:send))
87
+ utc_time = DateTime.new(year, month, day, hours, minutes, seconds, '0')
88
+
89
+ # adjust date if utc time reflects a wraparound from the local offset
90
+ local_offset = (geo_location.local_mean_time_offset + geo_location.standard_time_offset) / HOUR_MILLIS
91
+ if hours + local_offset > 18 && mode == :sunrise # sunrise after 6pm indicates the UTC date has occurred earlier
92
+ utc_time -= 1
93
+ elsif hours + local_offset < 6 && mode == :sunset # sunset before 6am indicates the UTC date has occurred later
94
+ utc_time += 1
95
+ end
96
+
97
+ convert_date_time_for_zone utc_time
98
+ end
99
+
100
+ def convert_date_time_for_zone(time)
101
+ converter = Util::TimeZoneConverter.new(geo_location.time_zone)
102
+ converter.modify_offset(time)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,243 @@
1
+ # encoding: UTF-8
2
+ module Zmanim::HebrewCalendar
3
+ class HebrewDateFormatter
4
+ extend Zmanim::Util::TextHelper
5
+ include Zmanim::Util::HebrewNumericFormatter
6
+
7
+ attr_accessor :hebrew_format, :use_long_hebrew_years, :long_week_format,
8
+ :transliterated_days_of_week, :transliterated_months, :transliterated_significant_days,
9
+ :transliterated_significant_tefilos, :transliterated_significant_shabbosos,
10
+ :hebrew_days_of_week, :hebrew_months, :hebrew_significant_days, :hebrew_significant_tefilos,
11
+ :hebrew_significant_shabbosos, :hebrew_omer_prefix
12
+
13
+ HEBREW_OMER_PREFIX = 'ב'
14
+ FORMATTED_DAYS_OF_WEEK = {
15
+ transliterated: Date::DAYNAMES[0..-2] + ['Shabbos'],
16
+ hebrew: %w(ראשון שני שלישי רביעי חמישי ששי שבת)
17
+ }
18
+
19
+ FORMATTED_MONTHS = {
20
+ transliterated: Zmanim::HebrewCalendar::JewishCalendar::MONTHS.each_with_object({}){|m, h|
21
+ h[m] = titleize(m)
22
+ }.merge(adar_i: 'Adar I', adar_ii: 'Adar II'),
23
+ hebrew: {
24
+ nissan: 'ניסן',
25
+ iyar: 'אייר',
26
+ sivan: 'סיון',
27
+ tammuz: 'תמוז',
28
+ av: 'אב',
29
+ elul: 'אלול',
30
+ tishrei: 'תשרי',
31
+ cheshvan: 'חשון',
32
+ kislev: 'כסלו',
33
+ teves: 'טבת',
34
+ shevat: 'שבט',
35
+ adar: 'אדר',
36
+ adar_i: 'אדר א',
37
+ adar_ii: 'אדר ב'
38
+ }
39
+ }
40
+
41
+ FORMATTED_SIGNIFICANT_DAYS = {
42
+ transliterated: Zmanim::HebrewCalendar::JewishCalendar::SIGNIFICANT_DAYS.each_with_object({}){|d, h|
43
+ h[d] = titleize(d)
44
+ }.merge(tzom_gedalyah: 'Fast of Gedalyah', tenth_of_teves: 'Tenth of Teves', tu_beshvat: "Tu B'Shvat",
45
+ taanis_esther: 'Fast of Esther', seventeen_of_tammuz: 'Seventeenth of Tammuz',
46
+ tisha_beav: "Tisha B'Av", tu_beav: "Tu B'Av", yom_hashoah: 'Yom HaShoah', yom_haatzmaut: "Yom Ha'atzmaut"),
47
+ hebrew: {
48
+ erev_rosh_hashana: 'ערב ראש השנה',
49
+ rosh_hashana: 'ראש השנה',
50
+ tzom_gedalyah: 'צום גדליה',
51
+ erev_yom_kippur: 'ערב יום כיפור',
52
+ yom_kippur: 'יום כיפור',
53
+ erev_succos: 'ערב סוכות',
54
+ succos: 'סוכות',
55
+ chol_hamoed_succos: 'חול המועד סוכות',
56
+ hoshana_rabbah: 'הושענה רבה',
57
+ shemini_atzeres: 'שמיני עצרת',
58
+ simchas_torah: 'שמחת תורה',
59
+ chanukah: 'חנוכה',
60
+ tenth_of_teves: 'עשרה בטבת',
61
+ tu_beshvat: 'ט״ו בשבט',
62
+ taanis_esther: 'תענית אסתר',
63
+ purim: 'פורים',
64
+ shushan_purim: 'שושן פורים',
65
+ purim_katan: 'פורים קטן',
66
+ shushan_purim_katan: 'שושן פורים קטן',
67
+ erev_pesach: 'ערב פסח',
68
+ pesach: 'פסח',
69
+ chol_hamoed_pesach: 'חול המועד פסח',
70
+ pesach_sheni: 'פסח שני',
71
+ erev_shavuos: 'ערב שבועות',
72
+ shavuos: 'שבועות',
73
+ seventeen_of_tammuz: 'שבעה עשר בתמוז',
74
+ tisha_beav: 'תשעה באב',
75
+ tu_beav: 'ט״ו באב',
76
+ yom_hashoah: 'יום השואה',
77
+ yom_hazikaron: 'יום הזכרון',
78
+ yom_haatzmaut: 'יום העצמאות',
79
+ yom_yerushalayim: 'יום ירושלים',
80
+ }
81
+ }
82
+
83
+ FORMATTED_SIGNIFICANT_TEFILOS = {
84
+ transliterated: Zmanim::HebrewCalendar::JewishCalendar::SIGNIFICANT_TEFILOS.each_with_object({}){|d, h|
85
+ h[d] = titleize(d)
86
+ }.merge(begin_mashiv_haruach: 'Mashiv Haruach (beginning Mussaf)',
87
+ end_mashiv_haruach: 'Mashiv Haruach (ending Mussaf)',
88
+ begin_morid_hatal: 'Morid Hatal (beginning Mussaf)'),
89
+ hebrew: {
90
+ yaaleh_veyavo: 'יעלה ויבא',
91
+ al_hanissim: 'על הנסים',
92
+ begin_mashiv_haruach: 'משיב הרוח (מתחילים במוסף)',
93
+ end_mashiv_haruach: 'משיב הרוח (מסיימים במוסף)',
94
+ mashiv_haruach: 'משיב הרוח',
95
+ begin_morid_hatal: 'מוריד הטל (מתחילים במוסף)',
96
+ morid_hatal: 'מוריד הטל',
97
+ vesein_tal_umatar: 'ותן טל ומטר',
98
+ vesein_beracha: 'ותן ברכה',
99
+ atah_yatzarta: 'אתה יצרת',
100
+ borchi_nafshi: 'ברכי נפשי',
101
+ }
102
+ }
103
+
104
+ FORMATTED_SIGNIFICANT_SHABBOSOS = {
105
+ transliterated: Zmanim::HebrewCalendar::JewishCalendar::SIGNIFICANT_SHABBOS.each_with_object({}){|d, h|
106
+ h[d] = titleize(d)
107
+ },
108
+ hebrew: {
109
+ parshas_shekalim: 'פרשת שקלים',
110
+ parshas_zachor: 'פרשת זכור',
111
+ parshas_parah: 'פרשת פרה',
112
+ parshas_hachodesh: 'פרשת החדש',
113
+ shabbos_hagadol: 'שבת הגדול',
114
+ shabbos_shuva: 'שבת שובה',
115
+ }
116
+ }
117
+
118
+ def initialize
119
+ super # hebrew numeric formatter
120
+ @long_week_format = true
121
+ @transliterated_days_of_week = FORMATTED_DAYS_OF_WEEK[:transliterated]
122
+ @transliterated_months = FORMATTED_MONTHS[:transliterated]
123
+ @transliterated_significant_days = FORMATTED_SIGNIFICANT_DAYS[:transliterated]
124
+ @transliterated_significant_tefilos = FORMATTED_SIGNIFICANT_TEFILOS[:transliterated]
125
+ @transliterated_significant_shabbosos = FORMATTED_SIGNIFICANT_SHABBOSOS[:transliterated]
126
+ @hebrew_days_of_week = FORMATTED_DAYS_OF_WEEK[:hebrew]
127
+ @hebrew_months = FORMATTED_MONTHS[:hebrew]
128
+ @hebrew_significant_days = FORMATTED_SIGNIFICANT_DAYS[:hebrew]
129
+ @hebrew_significant_tefilos = FORMATTED_SIGNIFICANT_TEFILOS[:hebrew]
130
+ @hebrew_significant_shabbosos = FORMATTED_SIGNIFICANT_SHABBOSOS[:hebrew]
131
+ @hebrew_omer_prefix = HEBREW_OMER_PREFIX
132
+ end
133
+
134
+ def format(date)
135
+ if hebrew_format
136
+ format_hebrew_number(date.jewish_day) + ' ' + format_month(date) + ' ' + format_hebrew_number(date.jewish_year)
137
+ else
138
+ "#{date.jewish_day} #{format_month(date)}, #{date.jewish_year}"
139
+ end
140
+ end
141
+
142
+ def format_month(date)
143
+ format_month_from_name(date.jewish_month_name, date.jewish_leap_year?)
144
+ end
145
+
146
+ def format_day_of_week(date)
147
+ format_day_of_week_from_number(date.day_of_week)
148
+ end
149
+
150
+ def format_hebrew_number(number)
151
+ super(number, use_long_hebrew_years)
152
+ end
153
+
154
+ def format_significant_day(calendar)
155
+ sd = calendar.significant_day
156
+ return '' unless sd
157
+ prefix = (day_number = calendar.day_of_chanukah) ? formatted_number(day_number) + ' ' : ''
158
+ prefix + formatted_significant_day(sd)
159
+ end
160
+
161
+ def format_rosh_chodesh(calendar)
162
+ return '' unless calendar.rosh_chodesh? || calendar.erev_rosh_chodesh?
163
+ month = calendar.jewish_month
164
+ day = calendar.jewish_day
165
+ if day != 1
166
+ month += 1
167
+ month = 1 if month > calendar.months_in_jewish_year
168
+ end
169
+ month_name = calendar.jewish_month_name(month)
170
+ formatted_rosh_chodesh(calendar.erev_rosh_chodesh?) + ' ' + format_month_from_name(month_name, calendar.jewish_leap_year?)
171
+ end
172
+
173
+ def format_omer(calendar)
174
+ return '' unless number = calendar.day_of_omer
175
+ if hebrew_format
176
+ format_hebrew_number(number) + ' ' + hebrew_omer_prefix + 'עומר'
177
+ else
178
+ number == 33 ? 'Lag BaOmer' : "Omer #{number}"
179
+ end
180
+ end
181
+
182
+ def format_kviah(year)
183
+ date = year.is_a?(Numeric) ? Zmanim::HebrewCalendar::JewishDate.new(year, 7, 1) : year
184
+ kviah = date.cheshvan_kislev_kviah
185
+ rosh_hashana_day = date.day_of_week
186
+ kviah_glyph = {chaseirim: 'ח', kesidran: 'כ', shelaimim: 'ש'}[kviah]
187
+ date.jewish_month = 1
188
+ pesach_day = date.day_of_week
189
+ "#{format_hebrew_number(rosh_hashana_day)}#{kviah_glyph}#{format_hebrew_number(pesach_day)}".delete(GERESH)
190
+ end
191
+
192
+ def format_tefilah_additions(calendar, customs={walled_city: false, nusach: :ashkenaz})
193
+ additions = calendar.tefilah_additions(walled_city: customs[:walled_city], nusach: customs[:nusach])
194
+ additions.map do |addition|
195
+ hebrew_format ?
196
+ hebrew_significant_tefilos[addition] :
197
+ transliterated_significant_tefilos[addition]
198
+ end
199
+ end
200
+
201
+ def format_significant_shabbos(calendar)
202
+ return '' unless shabbos = calendar.significant_shabbos
203
+ hebrew_format ?
204
+ hebrew_significant_shabbosos[shabbos] :
205
+ transliterated_significant_shabbosos[shabbos]
206
+ end
207
+
208
+ private
209
+
210
+ # We don't consider Rosh Chodesh similar to other significant days due to overlapping complexity with Chanuka
211
+ def formatted_rosh_chodesh(is_erev)
212
+ prefix = ''
213
+ prefix += (hebrew_format ? 'ערב ' : 'Erev ') if is_erev
214
+ prefix + (hebrew_format ? 'ראש חדש' : 'Rosh Chodesh')
215
+ end
216
+
217
+ def formatted_significant_day(sd)
218
+ hebrew_format ? hebrew_significant_days[sd] : transliterated_significant_days[sd]
219
+ end
220
+
221
+ def formatted_number(number)
222
+ hebrew_format ? format_hebrew_number(number) : number.to_s
223
+ end
224
+
225
+ def format_month_from_name(month_name, is_leap_year)
226
+ month_name = :adar_i if month_name == :adar && is_leap_year
227
+ if hebrew_format
228
+ suffix = use_geresh_gershayim & month_name.to_s.start_with?('adar_') ? Zmanim::Util::HebrewNumericFormatter::GERESH : ''
229
+ hebrew_months[month_name] + suffix
230
+ else
231
+ transliterated_months[month_name]
232
+ end
233
+ end
234
+
235
+ def format_day_of_week_from_number(number)
236
+ if hebrew_format
237
+ long_week_format ? hebrew_days_of_week[number - 1] : format_hebrew_number(number)
238
+ else
239
+ transliterated_days_of_week[number - 1]
240
+ end
241
+ end
242
+ end
243
+ end