diff --git a/internal/database/migrations.go b/internal/database/migrations.go index a9d231a4..2f6eaa35 100644 --- a/internal/database/migrations.go +++ b/internal/database/migrations.go @@ -1158,4 +1158,187 @@ var migrations = [...]func(tx *sql.Tx) error{ _, err = tx.Exec(sql) return err }, + // This migration replaces deprecated timezones by their equivalent on Debian Trixie. + func(tx *sql.Tx) (err error) { + var deprecatedTimeZoneMap = map[string]string{ + // Africa + "Africa/Asmera": "Africa/Asmara", + + // America - Argentina + "America/Argentina/ComodRivadavia": "America/Argentina/Catamarca", + "America/Buenos_Aires": "America/Argentina/Buenos_Aires", + "America/Catamarca": "America/Argentina/Catamarca", + "America/Cordoba": "America/Argentina/Cordoba", + "America/Jujuy": "America/Argentina/Jujuy", + "America/Mendoza": "America/Argentina/Mendoza", + "America/Rosario": "America/Argentina/Cordoba", + + // America - US + "America/Fort_Wayne": "America/Indiana/Indianapolis", + "America/Indianapolis": "America/Indiana/Indianapolis", + "America/Knox_IN": "America/Indiana/Knox", + "America/Louisville": "America/Kentucky/Louisville", + + // America - Greenland + "America/Godthab": "America/Nuuk", + + // Antarctica + "Antarctica/South_Pole": "Pacific/Auckland", + + // Asia + "Asia/Ashkhabad": "Asia/Ashgabat", + "Asia/Calcutta": "Asia/Kolkata", + "Asia/Choibalsan": "Asia/Ulaanbaatar", + "Asia/Chungking": "Asia/Chongqing", + "Asia/Dacca": "Asia/Dhaka", + "Asia/Katmandu": "Asia/Kathmandu", + "Asia/Macao": "Asia/Macau", + "Asia/Rangoon": "Asia/Yangon", + "Asia/Saigon": "Asia/Ho_Chi_Minh", + "Asia/Thimbu": "Asia/Thimphu", + "Asia/Ujung_Pandang": "Asia/Makassar", + "Asia/Ulan_Bator": "Asia/Ulaanbaatar", + + // Atlantic + "Atlantic/Faeroe": "Atlantic/Faroe", + + // Australia + "Australia/ACT": "Australia/Sydney", + "Australia/LHI": "Australia/Lord_Howe", + "Australia/North": "Australia/Darwin", + "Australia/NSW": "Australia/Sydney", + "Australia/Queensland": "Australia/Brisbane", + "Australia/South": "Australia/Adelaide", + "Australia/Tasmania": "Australia/Hobart", + "Australia/Victoria": "Australia/Melbourne", + "Australia/West": "Australia/Perth", + + // Brazil + "Brazil/Acre": "America/Rio_Branco", + "Brazil/DeNoronha": "America/Noronha", + "Brazil/East": "America/Sao_Paulo", + "Brazil/West": "America/Manaus", + + // Canada + "Canada/Atlantic": "America/Halifax", + "Canada/Central": "America/Winnipeg", + "Canada/Eastern": "America/Toronto", + "Canada/Mountain": "America/Edmonton", + "Canada/Newfoundland": "America/St_Johns", + "Canada/Pacific": "America/Vancouver", + "Canada/Saskatchewan": "America/Regina", + "Canada/Yukon": "America/Whitehorse", + + // Europe + "CET": "Europe/Paris", + "EET": "Europe/Sofia", + "Europe/Kiev": "Europe/Kyiv", + "Europe/Uzhgorod": "Europe/Kyiv", + "Europe/Zaporozhye": "Europe/Kyiv", + "MET": "Europe/Paris", + "WET": "Europe/Lisbon", + + // Chile + "Chile/Continental": "America/Santiago", + "Chile/EasterIsland": "Pacific/Easter", + + // Fixed offset and generic zones + "CST6CDT": "America/Chicago", + "EST": "America/New_York", + "EST5EDT": "America/New_York", + "HST": "Pacific/Honolulu", + "MST": "America/Denver", + "MST7MDT": "America/Denver", + "PST8PDT": "America/Los_Angeles", + + // Countries/Regions + "Cuba": "America/Havana", + "Egypt": "Africa/Cairo", + "Eire": "Europe/Dublin", + "GB": "Europe/London", + "GB-Eire": "Europe/London", + "Hongkong": "Asia/Hong_Kong", + "Iceland": "Atlantic/Reykjavik", + "Iran": "Asia/Tehran", + "Israel": "Asia/Jerusalem", + "Jamaica": "America/Jamaica", + "Japan": "Asia/Tokyo", + "Libya": "Africa/Tripoli", + "Poland": "Europe/Warsaw", + "Portugal": "Europe/Lisbon", + "PRC": "Asia/Shanghai", + "ROC": "Asia/Taipei", + "ROK": "Asia/Seoul", + "Singapore": "Asia/Singapore", + "Turkey": "Europe/Istanbul", + + // GMT variations + "GMT+0": "GMT", + "GMT-0": "GMT", + "GMT0": "GMT", + "Greenwich": "GMT", + "UCT": "UTC", + "Universal": "UTC", + "Zulu": "UTC", + + // Mexico + "Mexico/BajaNorte": "America/Tijuana", + "Mexico/BajaSur": "America/Mazatlan", + "Mexico/General": "America/Mexico_City", + + // US zones + "Navajo": "America/Denver", + "US/Alaska": "America/Anchorage", + "US/Aleutian": "America/Adak", + "US/Arizona": "America/Phoenix", + "US/Central": "America/Chicago", + "US/Eastern": "America/New_York", + "US/East-Indiana": "America/Indiana/Indianapolis", + "US/Hawaii": "Pacific/Honolulu", + "US/Indiana-Starke": "America/Indiana/Knox", + "US/Michigan": "America/Detroit", + "US/Mountain": "America/Denver", + "US/Pacific": "America/Los_Angeles", + "US/Samoa": "Pacific/Pago_Pago", + + // Pacific + "Kwajalein": "Pacific/Kwajalein", + "NZ": "Pacific/Auckland", + "NZ-CHAT": "Pacific/Chatham", + "Pacific/Enderbury": "Pacific/Kanton", + "Pacific/Ponape": "Pacific/Pohnpei", + "Pacific/Truk": "Pacific/Chuuk", + + // Special cases + "Factory": "UTC", // Factory is used for unconfigured systems + "W-SU": "Europe/Moscow", + } + + // Loop through each user and correct the timezone + rows, err := tx.Query(`SELECT id, timezone FROM users`) + if err != nil { + return err + } + + userTimezoneMap := make(map[int64]string) + for rows.Next() { + var userID int64 + var userTimezone string + if err := rows.Scan(&userID, &userTimezone); err != nil { + return err + } + userTimezoneMap[userID] = userTimezone + } + rows.Close() + + for userID, userTimezone := range userTimezoneMap { + if newTimezone, found := deprecatedTimeZoneMap[userTimezone]; found { + if _, err := tx.Exec(`UPDATE users SET timezone = $1 WHERE id = $2`, newTimezone, userID); err != nil { + return err + } + } + } + + return nil + }, } diff --git a/internal/storage/timezone.go b/internal/storage/timezone.go deleted file mode 100644 index f3748735..00000000 --- a/internal/storage/timezone.go +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -package storage // import "miniflux.app/v2/internal/storage" - -import ( - "fmt" - "strings" -) - -// Timezones returns all timezones supported by the database. -func (s *Storage) Timezones() (map[string]string, error) { - timezones := make(map[string]string) - rows, err := s.db.Query(`SELECT name FROM pg_timezone_names ORDER BY name ASC`) - if err != nil { - return nil, fmt.Errorf(`store: unable to fetch timezones: %v`, err) - } - defer rows.Close() - - for rows.Next() { - var timezone string - if err := rows.Scan(&timezone); err != nil { - return nil, fmt.Errorf(`store: unable to fetch timezones row: %v`, err) - } - - if !strings.HasPrefix(timezone, "posix") && !strings.HasPrefix(timezone, "SystemV") && timezone != "localtime" { - timezones[timezone] = timezone - } - } - - return timezones, nil -} diff --git a/internal/timezone/timezone.go b/internal/timezone/timezone.go index 1efd803d..d299dbf7 100644 --- a/internal/timezone/timezone.go +++ b/internal/timezone/timezone.go @@ -59,3 +59,464 @@ func getLocation(tz string) *time.Location { tzCache.Store(tz, loc) return loc } + +// AvailableTimezones returns a map of supported timezones. +// This list is taken from Postgres on Debian Trixie. +func AvailableTimezones() map[string]string { + timezones := []string{ + "Africa/Abidjan", + "Africa/Accra", + "Africa/Addis_Ababa", + "Africa/Algiers", + "Africa/Asmara", + "Africa/Bamako", + "Africa/Bangui", + "Africa/Banjul", + "Africa/Bissau", + "Africa/Blantyre", + "Africa/Brazzaville", + "Africa/Bujumbura", + "Africa/Cairo", + "Africa/Casablanca", + "Africa/Ceuta", + "Africa/Conakry", + "Africa/Dakar", + "Africa/Dar_es_Salaam", + "Africa/Djibouti", + "Africa/Douala", + "Africa/El_Aaiun", + "Africa/Freetown", + "Africa/Gaborone", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Juba", + "Africa/Kampala", + "Africa/Khartoum", + "Africa/Kigali", + "Africa/Kinshasa", + "Africa/Lagos", + "Africa/Libreville", + "Africa/Lome", + "Africa/Luanda", + "Africa/Lubumbashi", + "Africa/Lusaka", + "Africa/Malabo", + "Africa/Maputo", + "Africa/Maseru", + "Africa/Mbabane", + "Africa/Mogadishu", + "Africa/Monrovia", + "Africa/Nairobi", + "Africa/Ndjamena", + "Africa/Niamey", + "Africa/Nouakchott", + "Africa/Ouagadougou", + "Africa/Porto-Novo", + "Africa/Sao_Tome", + "Africa/Timbuktu", + "Africa/Tripoli", + "Africa/Tunis", + "Africa/Windhoek", + "America/Adak", + "America/Anchorage", + "America/Anguilla", + "America/Antigua", + "America/Araguaina", + "America/Argentina/Buenos_Aires", + "America/Argentina/Catamarca", + "America/Argentina/Cordoba", + "America/Argentina/Jujuy", + "America/Argentina/La_Rioja", + "America/Argentina/Mendoza", + "America/Argentina/Rio_Gallegos", + "America/Argentina/Salta", + "America/Argentina/San_Juan", + "America/Argentina/San_Luis", + "America/Argentina/Tucuman", + "America/Argentina/Ushuaia", + "America/Aruba", + "America/Asuncion", + "America/Atikokan", + "America/Atka", + "America/Bahia", + "America/Bahia_Banderas", + "America/Barbados", + "America/Belem", + "America/Belize", + "America/Blanc-Sablon", + "America/Boa_Vista", + "America/Bogota", + "America/Boise", + "America/Cambridge_Bay", + "America/Campo_Grande", + "America/Cancun", + "America/Caracas", + "America/Cayenne", + "America/Cayman", + "America/Chicago", + "America/Chihuahua", + "America/Ciudad_Juarez", + "America/Coral_Harbour", + "America/Costa_Rica", + "America/Coyhaique", + "America/Creston", + "America/Cuiaba", + "America/Curacao", + "America/Danmarkshavn", + "America/Dawson", + "America/Dawson_Creek", + "America/Denver", + "America/Detroit", + "America/Dominica", + "America/Edmonton", + "America/Eirunepe", + "America/El_Salvador", + "America/Ensenada", + "America/Fortaleza", + "America/Fort_Nelson", + "America/Glace_Bay", + "America/Goose_Bay", + "America/Grand_Turk", + "America/Grenada", + "America/Guadeloupe", + "America/Guatemala", + "America/Guayaquil", + "America/Guyana", + "America/Halifax", + "America/Havana", + "America/Hermosillo", + "America/Indiana/Indianapolis", + "America/Indiana/Knox", + "America/Indiana/Marengo", + "America/Indiana/Petersburg", + "America/Indiana/Tell_City", + "America/Indiana/Vevay", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Inuvik", + "America/Iqaluit", + "America/Jamaica", + "America/Juneau", + "America/Kentucky/Louisville", + "America/Kentucky/Monticello", + "America/Kralendijk", + "America/La_Paz", + "America/Lima", + "America/Los_Angeles", + "America/Lower_Princes", + "America/Maceio", + "America/Managua", + "America/Manaus", + "America/Marigot", + "America/Martinique", + "America/Matamoros", + "America/Mazatlan", + "America/Menominee", + "America/Merida", + "America/Metlakatla", + "America/Mexico_City", + "America/Miquelon", + "America/Moncton", + "America/Monterrey", + "America/Montevideo", + "America/Montreal", + "America/Montserrat", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Nome", + "America/Noronha", + "America/North_Dakota/Beulah", + "America/North_Dakota/Center", + "America/North_Dakota/New_Salem", + "America/Nuuk", + "America/Ojinaga", + "America/Panama", + "America/Pangnirtung", + "America/Paramaribo", + "America/Phoenix", + "America/Port-au-Prince", + "America/Porto_Acre", + "America/Port_of_Spain", + "America/Porto_Velho", + "America/Puerto_Rico", + "America/Punta_Arenas", + "America/Rainy_River", + "America/Rankin_Inlet", + "America/Recife", + "America/Regina", + "America/Resolute", + "America/Rio_Branco", + "America/Santa_Isabel", + "America/Santarem", + "America/Santiago", + "America/Santo_Domingo", + "America/Sao_Paulo", + "America/Scoresbysund", + "America/Shiprock", + "America/Sitka", + "America/St_Barthelemy", + "America/St_Johns", + "America/St_Kitts", + "America/St_Lucia", + "America/St_Thomas", + "America/St_Vincent", + "America/Swift_Current", + "America/Tegucigalpa", + "America/Thule", + "America/Thunder_Bay", + "America/Tijuana", + "America/Toronto", + "America/Tortola", + "America/Vancouver", + "America/Virgin", + "America/Whitehorse", + "America/Winnipeg", + "America/Yakutat", + "America/Yellowknife", + "Antarctica/Casey", + "Antarctica/Davis", + "Antarctica/DumontDUrville", + "Antarctica/Macquarie", + "Antarctica/Mawson", + "Antarctica/McMurdo", + "Antarctica/Palmer", + "Antarctica/Rothera", + "Antarctica/Syowa", + "Antarctica/Troll", + "Antarctica/Vostok", + "Arctic/Longyearbyen", + "Asia/Aden", + "Asia/Almaty", + "Asia/Amman", + "Asia/Anadyr", + "Asia/Aqtau", + "Asia/Aqtobe", + "Asia/Ashgabat", + "Asia/Atyrau", + "Asia/Baghdad", + "Asia/Bahrain", + "Asia/Baku", + "Asia/Bangkok", + "Asia/Barnaul", + "Asia/Beirut", + "Asia/Bishkek", + "Asia/Brunei", + "Asia/Chita", + "Asia/Chongqing", + "Asia/Colombo", + "Asia/Damascus", + "Asia/Dhaka", + "Asia/Dili", + "Asia/Dubai", + "Asia/Dushanbe", + "Asia/Famagusta", + "Asia/Gaza", + "Asia/Harbin", + "Asia/Hebron", + "Asia/Ho_Chi_Minh", + "Asia/Hong_Kong", + "Asia/Hovd", + "Asia/Irkutsk", + "Asia/Istanbul", + "Asia/Jakarta", + "Asia/Jayapura", + "Asia/Jerusalem", + "Asia/Kabul", + "Asia/Kamchatka", + "Asia/Karachi", + "Asia/Kashgar", + "Asia/Kathmandu", + "Asia/Khandyga", + "Asia/Kolkata", + "Asia/Krasnoyarsk", + "Asia/Kuala_Lumpur", + "Asia/Kuching", + "Asia/Kuwait", + "Asia/Macau", + "Asia/Magadan", + "Asia/Makassar", + "Asia/Manila", + "Asia/Muscat", + "Asia/Nicosia", + "Asia/Novokuznetsk", + "Asia/Novosibirsk", + "Asia/Omsk", + "Asia/Oral", + "Asia/Phnom_Penh", + "Asia/Pontianak", + "Asia/Pyongyang", + "Asia/Qatar", + "Asia/Qostanay", + "Asia/Qyzylorda", + "Asia/Riyadh", + "Asia/Sakhalin", + "Asia/Samarkand", + "Asia/Seoul", + "Asia/Shanghai", + "Asia/Singapore", + "Asia/Srednekolymsk", + "Asia/Taipei", + "Asia/Tashkent", + "Asia/Tbilisi", + "Asia/Tehran", + "Asia/Tel_Aviv", + "Asia/Thimphu", + "Asia/Tokyo", + "Asia/Tomsk", + "Asia/Ulaanbaatar", + "Asia/Urumqi", + "Asia/Ust-Nera", + "Asia/Vientiane", + "Asia/Vladivostok", + "Asia/Yakutsk", + "Asia/Yangon", + "Asia/Yekaterinburg", + "Asia/Yerevan", + "Atlantic/Azores", + "Atlantic/Bermuda", + "Atlantic/Canary", + "Atlantic/Cape_Verde", + "Atlantic/Faroe", + "Atlantic/Jan_Mayen", + "Atlantic/Madeira", + "Atlantic/Reykjavik", + "Atlantic/South_Georgia", + "Atlantic/Stanley", + "Atlantic/St_Helena", + "Australia/Adelaide", + "Australia/Brisbane", + "Australia/Broken_Hill", + "Australia/Canberra", + "Australia/Currie", + "Australia/Darwin", + "Australia/Eucla", + "Australia/Hobart", + "Australia/Lindeman", + "Australia/Lord_Howe", + "Australia/Melbourne", + "Australia/Perth", + "Australia/Sydney", + "Australia/Yancowinna", + "Europe/Amsterdam", + "Europe/Andorra", + "Europe/Astrakhan", + "Europe/Athens", + "Europe/Belfast", + "Europe/Belgrade", + "Europe/Berlin", + "Europe/Bratislava", + "Europe/Brussels", + "Europe/Bucharest", + "Europe/Budapest", + "Europe/Busingen", + "Europe/Chisinau", + "Europe/Copenhagen", + "Europe/Dublin", + "Europe/Gibraltar", + "Europe/Guernsey", + "Europe/Helsinki", + "Europe/Isle_of_Man", + "Europe/Istanbul", + "Europe/Jersey", + "Europe/Kaliningrad", + "Europe/Kirov", + "Europe/Kyiv", + "Europe/Lisbon", + "Europe/Ljubljana", + "Europe/London", + "Europe/Luxembourg", + "Europe/Madrid", + "Europe/Malta", + "Europe/Mariehamn", + "Europe/Minsk", + "Europe/Monaco", + "Europe/Moscow", + "Europe/Nicosia", + "Europe/Oslo", + "Europe/Paris", + "Europe/Podgorica", + "Europe/Prague", + "Europe/Riga", + "Europe/Rome", + "Europe/Samara", + "Europe/San_Marino", + "Europe/Sarajevo", + "Europe/Saratov", + "Europe/Simferopol", + "Europe/Skopje", + "Europe/Sofia", + "Europe/Stockholm", + "Europe/Tallinn", + "Europe/Tirane", + "Europe/Tiraspol", + "Europe/Ulyanovsk", + "Europe/Vaduz", + "Europe/Vatican", + "Europe/Vienna", + "Europe/Vilnius", + "Europe/Volgograd", + "Europe/Warsaw", + "Europe/Zagreb", + "Europe/Zurich", + "GMT", + "Indian/Antananarivo", + "Indian/Chagos", + "Indian/Christmas", + "Indian/Cocos", + "Indian/Comoro", + "Indian/Kerguelen", + "Indian/Mahe", + "Indian/Maldives", + "Indian/Mauritius", + "Indian/Mayotte", + "Indian/Reunion", + "Pacific/Apia", + "Pacific/Auckland", + "Pacific/Bougainville", + "Pacific/Chatham", + "Pacific/Chuuk", + "Pacific/Easter", + "Pacific/Efate", + "Pacific/Fakaofo", + "Pacific/Fiji", + "Pacific/Funafuti", + "Pacific/Galapagos", + "Pacific/Gambier", + "Pacific/Guadalcanal", + "Pacific/Guam", + "Pacific/Honolulu", + "Pacific/Johnston", + "Pacific/Kanton", + "Pacific/Kiritimati", + "Pacific/Kosrae", + "Pacific/Kwajalein", + "Pacific/Majuro", + "Pacific/Marquesas", + "Pacific/Midway", + "Pacific/Nauru", + "Pacific/Niue", + "Pacific/Norfolk", + "Pacific/Noumea", + "Pacific/Pago_Pago", + "Pacific/Palau", + "Pacific/Pitcairn", + "Pacific/Pohnpei", + "Pacific/Port_Moresby", + "Pacific/Rarotonga", + "Pacific/Saipan", + "Pacific/Samoa", + "Pacific/Tahiti", + "Pacific/Tarawa", + "Pacific/Tongatapu", + "Pacific/Wake", + "Pacific/Wallis", + "Pacific/Yap", + "UTC", + } + availableTimezones := make(map[string]string, len(timezones)) + for _, tz := range timezones { + availableTimezones[tz] = tz + } + return availableTimezones +} diff --git a/internal/ui/settings_show.go b/internal/ui/settings_show.go index fdbfff04..1cdb005a 100644 --- a/internal/ui/settings_show.go +++ b/internal/ui/settings_show.go @@ -10,6 +10,7 @@ import ( "miniflux.app/v2/internal/http/response/html" "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" + "miniflux.app/v2/internal/timezone" "miniflux.app/v2/internal/ui/form" "miniflux.app/v2/internal/ui/session" "miniflux.app/v2/internal/ui/view" @@ -50,12 +51,6 @@ func (h *handler) showSettingsPage(w http.ResponseWriter, r *http.Request) { OpenExternalLinksInNewTab: user.OpenExternalLinksInNewTab, } - timezones, err := h.store.Timezones() - if err != nil { - html.ServerError(w, r, err) - return - } - creds, err := h.store.WebAuthnCredentialsByUserID(user.ID) if err != nil { html.ServerError(w, r, err) @@ -73,7 +68,7 @@ func (h *handler) showSettingsPage(w http.ResponseWriter, r *http.Request) { }) view.Set("themes", model.Themes()) view.Set("languages", locale.AvailableLanguages) - view.Set("timezones", timezones) + view.Set("timezones", timezone.AvailableTimezones()) view.Set("menu", "settings") view.Set("user", user) view.Set("countUnread", h.store.CountUnreadEntries(user.ID)) diff --git a/internal/ui/settings_update.go b/internal/ui/settings_update.go index 89ef0327..5c1554c8 100644 --- a/internal/ui/settings_update.go +++ b/internal/ui/settings_update.go @@ -11,6 +11,7 @@ import ( "miniflux.app/v2/internal/http/route" "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" + "miniflux.app/v2/internal/timezone" "miniflux.app/v2/internal/ui/form" "miniflux.app/v2/internal/ui/session" "miniflux.app/v2/internal/ui/view" @@ -24,12 +25,6 @@ func (h *handler) updateSettings(w http.ResponseWriter, r *http.Request) { return } - timezones, err := h.store.Timezones() - if err != nil { - html.ServerError(w, r, err) - return - } - creds, err := h.store.WebAuthnCredentialsByUserID(user.ID) if err != nil { html.ServerError(w, r, err) @@ -49,7 +44,7 @@ func (h *handler) updateSettings(w http.ResponseWriter, r *http.Request) { }) view.Set("themes", model.Themes()) view.Set("languages", locale.AvailableLanguages) - view.Set("timezones", timezones) + view.Set("timezones", timezone.AvailableTimezones()) view.Set("menu", "settings") view.Set("user", user) view.Set("countUnread", h.store.CountUnreadEntries(user.ID)) diff --git a/internal/validator/user.go b/internal/validator/user.go index 3d8fa368..1ac403dd 100644 --- a/internal/validator/user.go +++ b/internal/validator/user.go @@ -11,6 +11,7 @@ import ( "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" "miniflux.app/v2/internal/storage" + "miniflux.app/v2/internal/timezone" ) // ValidateUserCreationWithPassword validates user creation with a password. @@ -63,7 +64,7 @@ func ValidateUserModification(store *storage.Storage, userID int64, changes *mod } if changes.Timezone != nil { - if err := validateTimezone(store, *changes.Timezone); err != nil { + if err := validateTimezone(*changes.Timezone); err != nil { return err } } @@ -200,13 +201,8 @@ func validateLanguage(language string) *locale.LocalizedError { return nil } -func validateTimezone(store *storage.Storage, timezone string) *locale.LocalizedError { - timezones, err := store.Timezones() - if err != nil { - return locale.NewLocalizedError(err.Error()) - } - - if _, found := timezones[timezone]; !found { +func validateTimezone(timezoneValue string) *locale.LocalizedError { + if _, found := timezone.AvailableTimezones()[timezoneValue]; !found { return locale.NewLocalizedError("error.invalid_timezone") } return nil