167 lines
3.7 KiB
Go
167 lines
3.7 KiB
Go
package briefing
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"time"
|
|
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/forecast"
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/timeutil"
|
|
)
|
|
|
|
func rangeLabel(value forecast.Range) string {
|
|
if value.Min == nil && value.Max == nil {
|
|
return ""
|
|
}
|
|
if value.Min != nil && value.Max != nil {
|
|
low := roundedInt(value.Min)
|
|
high := roundedInt(value.Max)
|
|
if low != nil && high != nil && *low == *high {
|
|
return fmt.Sprintf("%d", *low)
|
|
}
|
|
return fmt.Sprintf("%d-%d", *low, *high)
|
|
}
|
|
if value.Min != nil {
|
|
low := roundedInt(value.Min)
|
|
return fmt.Sprintf("%d", *low)
|
|
}
|
|
high := roundedInt(value.Max)
|
|
return fmt.Sprintf("%d", *high)
|
|
}
|
|
|
|
func daypartApparentRangeLabel(value forecast.Range) string {
|
|
if value.Min == nil && value.Max == nil {
|
|
return ""
|
|
}
|
|
return rangeLabel(value)
|
|
}
|
|
|
|
func roundedInt(value *float64) *int {
|
|
if value == nil {
|
|
return nil
|
|
}
|
|
rounded := int(*value + 0.5)
|
|
if *value < 0 {
|
|
rounded = int(*value - 0.5)
|
|
}
|
|
return &rounded
|
|
}
|
|
|
|
func windDirectionLabel(degrees *float64) string {
|
|
if degrees == nil {
|
|
return ""
|
|
}
|
|
labels := []string{"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"}
|
|
normalized := math.Mod(*degrees, 360)
|
|
if normalized < 0 {
|
|
normalized += 360
|
|
}
|
|
sector := int(math.Floor((normalized+11.25)/22.5)) % len(labels)
|
|
return labels[sector]
|
|
}
|
|
|
|
func windDirectionTextLabel(degrees *float64) string {
|
|
if degrees == nil {
|
|
return ""
|
|
}
|
|
labels := []string{
|
|
"north",
|
|
"north-northeast",
|
|
"northeast",
|
|
"east-northeast",
|
|
"east",
|
|
"east-southeast",
|
|
"southeast",
|
|
"south-southeast",
|
|
"south",
|
|
"south-southwest",
|
|
"southwest",
|
|
"west-southwest",
|
|
"west",
|
|
"west-northwest",
|
|
"northwest",
|
|
"north-northwest",
|
|
}
|
|
normalized := math.Mod(*degrees, 360)
|
|
if normalized < 0 {
|
|
normalized += 360
|
|
}
|
|
sector := int(math.Floor((normalized+11.25)/22.5)) % len(labels)
|
|
return labels[sector]
|
|
}
|
|
|
|
func timedClockLabel(value *forecast.TimedValue, timezone string) string {
|
|
if value == nil {
|
|
return ""
|
|
}
|
|
return clockLabel(value.Time, timezone)
|
|
}
|
|
|
|
func friendlyPeriodBeginsLabel(period timeutil.Period, timezone string) string {
|
|
if !period.IsValid() {
|
|
return ""
|
|
}
|
|
return friendlyDateTimeLabel(period.Start, timezone)
|
|
}
|
|
|
|
func friendlyPeriodEndsLabel(period timeutil.Period, timezone string) string {
|
|
if !period.IsValid() {
|
|
return ""
|
|
}
|
|
return friendlyDateTimeLabel(period.End, timezone)
|
|
}
|
|
|
|
func friendlyDateTimeLabel(value time.Time, timezone string) string {
|
|
if value.IsZero() {
|
|
return ""
|
|
}
|
|
location, err := timeutil.LoadLocation(timezone)
|
|
if err != nil {
|
|
location = time.UTC
|
|
}
|
|
return value.In(location).Format("2006-01-02 at 3:04 PM")
|
|
}
|
|
|
|
func friendlyDateLabel(date string, timezone string) string {
|
|
location, err := timeutil.LoadLocation(timezone)
|
|
if err != nil {
|
|
location = time.UTC
|
|
}
|
|
parsed, err := time.ParseInLocation(timeutil.DateLayout, date, location)
|
|
if err != nil {
|
|
return date
|
|
}
|
|
return parsed.Format("Monday, January 2, 2006")
|
|
}
|
|
|
|
func localDateLabel(value time.Time, timezone string) string {
|
|
if value.IsZero() {
|
|
return ""
|
|
}
|
|
location, err := timeutil.LoadLocation(timezone)
|
|
if err != nil {
|
|
location = time.UTC
|
|
}
|
|
return value.In(location).Format(timeutil.DateLayout)
|
|
}
|
|
|
|
func clockLabel(value time.Time, timezone string) string {
|
|
location, err := timeutil.LoadLocation(timezone)
|
|
if err != nil {
|
|
location = time.UTC
|
|
}
|
|
label := value.In(location).Format("3 PM")
|
|
if label == "12 AM" && value.In(location).Minute() == 0 {
|
|
return "12 AM"
|
|
}
|
|
return label
|
|
}
|
|
|
|
func hourMinuteLabel(value time.Time, timezone string) string {
|
|
location, err := timeutil.LoadLocation(timezone)
|
|
if err != nil {
|
|
location = time.UTC
|
|
}
|
|
return value.In(location).Format("3:04 PM")
|
|
}
|