Datepickers on native time.Time / lagoon.Date fields, file uploads on materials, readings and class sessions managed from the course form (course_id made nullable).
61 lines
1.8 KiB
Go
61 lines
1.8 KiB
Go
package models
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
_ "time/tzdata" // Europe/Warsaw must resolve on hosts without zoneinfo.
|
|
|
|
"git.golem15.com/golem15/summercms/modules/lagoon"
|
|
)
|
|
|
|
// Location is the time zone the programme runs in. Timestamps are stored in
|
|
// UTC (TIMESTAMPTZ) and shown in this zone; a date or time typed without an
|
|
// offset is read in it.
|
|
var Location = mustLoadLocation("Europe/Warsaw")
|
|
|
|
func mustLoadLocation(name string) *time.Location {
|
|
loc, err := time.LoadLocation(name)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("jz.bm: load location %s: %v", name, err))
|
|
}
|
|
return loc
|
|
}
|
|
|
|
// dateTimeLayouts are the forms ParseDateTime accepts. RFC 3339 carries its
|
|
// own offset; the others are wall-clock times in Location.
|
|
var dateTimeLayouts = []string{
|
|
"2006-01-02T15:04",
|
|
"2006-01-02 15:04",
|
|
"2006-01-02T15:04:05",
|
|
"2006-01-02 15:04:05",
|
|
}
|
|
|
|
// ParseDateTime reads an RFC 3339 timestamp, or a wall-clock time
|
|
// ("2026-10-03 08:00") in Location. The seed file uses these forms.
|
|
func ParseDateTime(s string) (time.Time, error) {
|
|
s = strings.TrimSpace(s)
|
|
if t, err := time.Parse(time.RFC3339, s); err == nil {
|
|
return t, nil
|
|
}
|
|
for _, layout := range dateTimeLayouts {
|
|
if t, err := time.ParseInLocation(layout, s, Location); err == nil {
|
|
return t, nil
|
|
}
|
|
}
|
|
return time.Time{}, fmt.Errorf("jz.bm: %q is not a date and time", s)
|
|
}
|
|
|
|
// ParseDate reads a YYYY-MM-DD calendar date.
|
|
func ParseDate(s string) (lagoon.Date, error) {
|
|
d, err := lagoon.ParseDate(strings.TrimSpace(s))
|
|
if err != nil {
|
|
return lagoon.Date{}, fmt.Errorf("jz.bm: %q is not a YYYY-MM-DD date", s)
|
|
}
|
|
return d, nil
|
|
}
|
|
|
|
// FormatDateTime is the API form of a timestamp: RFC 3339 in Location
|
|
// ("2026-10-03T08:00:00+02:00").
|
|
func FormatDateTime(t time.Time) string { return t.In(Location).Format(time.RFC3339) }
|