mirror of
https://git.sr.ht/~phw/scotty
synced 2025-04-29 21:27:05 +02:00
scrobblerlog: consider timezone from parsed file
This commit is contained in:
parent
9184d2c3cf
commit
69665bc286
1 changed files with 36 additions and 6 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright © 2023 Philipp Wolfer <phw@uploadedlobster.com>
|
||||
Copyright © 2023-2025 Philipp Wolfer <phw@uploadedlobster.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -38,6 +38,7 @@ type ScrobblerLog struct {
|
|||
Timezone string
|
||||
Client string
|
||||
Listens models.ListensList
|
||||
location *time.Location
|
||||
}
|
||||
|
||||
func Parse(data io.Reader, includeSkipped bool) (ScrobblerLog, error) {
|
||||
|
@ -79,8 +80,7 @@ func Parse(data io.Reader, includeSkipped bool) (ScrobblerLog, error) {
|
|||
continue
|
||||
}
|
||||
|
||||
client := strings.Split(result.Client, " ")[0]
|
||||
listen, err := rowToListen(row, client)
|
||||
listen, err := result.rowToListen(row)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
@ -138,14 +138,19 @@ func ReadHeader(reader *bufio.Reader, log *ScrobblerLog) error {
|
|||
err = fmt.Errorf("not a scrobbler log file")
|
||||
}
|
||||
|
||||
// The timezone can be set to "UTC" or "UNKNOWN", if the device writing
|
||||
// the log knows the time, but not the timezone.
|
||||
timezone, found := strings.CutPrefix(text, "#TZ/")
|
||||
if found {
|
||||
log.Timezone = timezone
|
||||
log.location = locationFromTimezone(log.Timezone)
|
||||
continue
|
||||
}
|
||||
|
||||
client, found := strings.CutPrefix(text, "#CLIENT/")
|
||||
if found {
|
||||
log.Client = client
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,7 +176,7 @@ func WriteHeader(writer io.Writer, log *ScrobblerLog) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func rowToListen(row []string, client string) (models.Listen, error) {
|
||||
func (l ScrobblerLog) rowToListen(row []string) (models.Listen, error) {
|
||||
var listen models.Listen
|
||||
trackNumber, err := strconv.Atoi(row[3])
|
||||
if err != nil {
|
||||
|
@ -183,11 +188,12 @@ func rowToListen(row []string, client string) (models.Listen, error) {
|
|||
return listen, err
|
||||
}
|
||||
|
||||
timestamp, err := strconv.Atoi(row[6])
|
||||
timestamp, err := strconv.ParseInt(row[6], 10, 64)
|
||||
if err != nil {
|
||||
return listen, err
|
||||
}
|
||||
|
||||
client := strings.Split(l.Client, " ")[0]
|
||||
listen = models.Listen{
|
||||
Track: models.Track{
|
||||
ArtistNames: []string{row[0]},
|
||||
|
@ -200,7 +206,7 @@ func rowToListen(row []string, client string) (models.Listen, error) {
|
|||
"media_player": client,
|
||||
},
|
||||
},
|
||||
ListenedAt: time.Unix(int64(timestamp), 0),
|
||||
ListenedAt: timeFromLocalTimestamp(timestamp, l.location),
|
||||
}
|
||||
|
||||
if len(row) > 7 {
|
||||
|
@ -209,3 +215,27 @@ func rowToListen(row []string, client string) (models.Listen, error) {
|
|||
|
||||
return listen, nil
|
||||
}
|
||||
|
||||
// Convert the timezone string from the header to a time.Location.
|
||||
// Often this is set to "UNKNOWN" in the log file, in which case it defaults
|
||||
// to UTC.
|
||||
func locationFromTimezone(timezone string) *time.Location {
|
||||
location, err := time.LoadLocation(timezone)
|
||||
if err != nil {
|
||||
return time.UTC
|
||||
}
|
||||
return location
|
||||
}
|
||||
|
||||
// Convert a Unix timestamp to a time.Time object, but treat the timestamp
|
||||
// as being in the given location's timezone instead of UTC.
|
||||
func timeFromLocalTimestamp(timestamp int64, location *time.Location) time.Time {
|
||||
t := time.Unix(timestamp, 0)
|
||||
|
||||
// The time is now in UTC. Get the offset to the requested timezone.
|
||||
_, offset := t.In(location).Zone()
|
||||
if offset != 0 {
|
||||
t = t.Add(time.Duration(offset) * time.Second)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue