module BomForecastApi
BomForecastApi — daily forecast via BOM public API.
Public Instance Methods
Source
# File lib/bom_forecast_api.rb, line 16 def fetch_daily(grid, timezone, date, fetch:) date_text = date.is_a?(Date) ? date.iso8601 : date.to_s tz = URI.encode_www_form_component(timezone.to_s) path = "/forecasts/daily/#{grid["x"]}/#{grid["y"]}?timezone=#{tz}&fcstDate=#{date_text}" BomApi.fetch_json(path, fetch: fetch) end
Source
# File lib/bom_forecast_api.rb, line 136 def format_issued(issue_time, timezone) return "" unless issue_time zone = TZInfo::Timezone.get(timezone) period = zone.period_for_utc(issue_time.utc) abbr = period.abbreviation.to_s time_text = issue_time.strftime("%-l:%M %P").sub("am", "am").sub("pm", "pm") date_text = issue_time.strftime("%A %-d %B %Y") "Forecast issued at #{time_text} #{abbr} on #{date_text}." rescue StandardError "" end
Source
# File lib/bom_forecast_api.rb, line 124 def format_period(local_date, issue_date:, timezone:) weekday = local_date.strftime("%A") if issue_date && local_date == issue_date "Forecast for the rest of #{weekday}" else local_date.strftime("%A %-d %B") end rescue StandardError weekday end
Source
# File lib/bom_forecast_api.rb, line 90 def format_rainfall(precip) amount = precip["exceeding_50percentchance_total_mm"] return "0 mm" if amount.nil? || amount.to_f <= 0 upper = amount.to_f upper == upper.round ? "0 to #{upper.round} mm" : "0 to #{upper} mm" end
Source
# File lib/bom_forecast_api.rb, line 99 def format_temp(value) return nil if value.nil? BomForecast.normalize_value("#{value} °C") end
Source
# File lib/bom_forecast_api.rb, line 116 def local_date_for(date_utc, timezone) zone = TZInfo::Timezone.get(timezone) zone.to_local(Time.parse(date_utc).utc).to_date rescue StandardError Date.parse(date_utc.to_s[0, 10]) end
Source
# File lib/bom_forecast_api.rb, line 23 def lookup(api_place, fetch:) issue_date = Date.today json = fetch_daily(api_place[:grid], api_place[:timezone], issue_date, fetch: fetch) parse_forecast(json, place_name: api_place[:name]) rescue StandardError nil end
Source
# File lib/bom_forecast_api.rb, line 51 def parse_day(entry, issue_date:, timezone:, index:) air = entry.dig("atm", "surf_air") return nil unless air local_date = local_date_for(entry["date_utc"], timezone) period = format_period(local_date, issue_date: issue_date, timezone: timezone) precip = air["precip"] || {} rain_chance = rain_chance_for(precip, rest_of_today: period.match?(/rest of/i)) rainfall = format_rainfall(precip) weather = BomWeatherCodes.lookup(air.dig("weather", "icon_code")) description = weather[:precis] min = format_temp(air["temp_min_cel"]) max = format_temp(air["temp_max_cel"]) { period: period, condition: weather[:condition], min: min, max: max, rainfall: rainfall, rain_chance: rain_chance, description: description, summary: description } end
Source
# File lib/bom_forecast_api.rb, line 31 def parse_forecast(json, place_name:) daily = json.dig("fcst", "daily") return nil unless daily&.any? timezone = json.dig("meta", "local_timezone") || "Australia/Sydney" issue_time = parse_issue_time(json.dig("meta", "issue_time_utc"), timezone) issue_date = issue_time&.to_date days = daily.filter_map.with_index do |entry, index| parse_day(entry, issue_date: issue_date, timezone: timezone, index: index) end return nil if days.empty? { place: place_name.to_s, issued: format_issued(issue_time, timezone), days: days } end
Source
# File lib/bom_forecast_api.rb, line 106 def parse_issue_time(issue_time_utc, timezone) return nil if issue_time_utc.to_s.strip.empty? zone = TZInfo::Timezone.get(timezone) zone.to_local(Time.parse(issue_time_utc).utc) rescue StandardError nil end
Source
# File lib/bom_forecast_api.rb, line 78 def rain_chance_for(precip, rest_of_today:) percent = if rest_of_today precip["any_restofday_probability_percent"] || precip["any_probability_percent"] else precip["any_probability_percent"] end return nil if percent.nil? "#{percent.round}%" end