szabadpalya/api/internal/hu/format.go

94 lines
2.2 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package hu holds the Hungarian-locale formatting the server needs for share
// metadata and share images. The browser keeps using Intl for everything it
// renders itself; this exists because og: tags and PNGs are produced here.
package hu
import (
"strconv"
"strings"
"time"
"unicode"
)
// groupSeparator is U+00A0, which is what Intl.NumberFormat("hu-HU") emits.
// A plain space here would make the share card disagree with the page.
const groupSeparator = " "
func FormatNumber(n int) string {
s := strconv.Itoa(n)
neg := strings.HasPrefix(s, "-")
s = strings.TrimPrefix(s, "-")
var b strings.Builder
for i, r := range s {
if i > 0 && (len(s)-i)%3 == 0 {
b.WriteString(groupSeparator)
}
b.WriteRune(r)
}
if neg {
return "-" + b.String()
}
return b.String()
}
// FormatHUF renders 1351600 as "1 351 600 Ft".
func FormatHUF(n int) string { return FormatNumber(n) + " Ft" }
func ProgressPct(raised, goal int) int {
if goal <= 0 {
return 0
}
return int(float64(raised)/float64(goal)*100 + 0.5)
}
// DaysLeft counts whole days until the end of the closing day in Budapest —
// SPEC.md section 6. Never negative: a finished campaign has zero days left,
// not a negative countdown.
func DaysLeft(endsAt string, loc *time.Location, now time.Time) int {
d, err := time.ParseInLocation("2006-01-02", endsAt, loc)
if err != nil {
return 0
}
end := d.Add(24*time.Hour - time.Second)
diff := end.Sub(now)
if diff <= 0 {
return 0
}
days := int(diff / (24 * time.Hour))
if diff%(24*time.Hour) > 0 {
days++
}
return days
}
var accentFolds = map[rune]rune{
'á': 'a', 'é': 'e', 'í': 'i', 'ó': 'o', 'ö': 'o', 'ő': 'o',
'ú': 'u', 'ü': 'u', 'ű': 'u',
}
// Slugify mirrors the browser-side helper so a slug the editor previews is the
// slug that gets stored.
func Slugify(input string) string {
var b strings.Builder
for _, r := range strings.ToLower(input) {
if folded, ok := accentFolds[r]; ok {
r = folded
}
if (r >= 'a' && r <= 'z') || unicode.IsDigit(r) {
b.WriteRune(r)
} else {
b.WriteRune('-')
}
}
slug := b.String()
for strings.Contains(slug, "--") {
slug = strings.ReplaceAll(slug, "--", "-")
}
slug = strings.Trim(slug, "-")
if len(slug) > 80 {
slug = strings.Trim(slug[:80], "-")
}
return slug
}