mirror of
https://git.sr.ht/~phw/scotty
synced 2025-04-30 05:37:05 +02:00
parent
0f4b04c641
commit
ed191d2f15
5 changed files with 68 additions and 22 deletions
|
@ -71,10 +71,12 @@ type Record struct {
|
|||
|
||||
// Represents a scrobbler log file.
|
||||
type ScrobblerLog struct {
|
||||
TZ TZInfo
|
||||
Client string
|
||||
Records []Record
|
||||
location *time.Location
|
||||
TZ TZInfo
|
||||
Client string
|
||||
Records []Record
|
||||
// Timezone to be used for timestamps in the log file,
|
||||
// if TZ is set to [TZ_UNKNOWN].
|
||||
FallbackTimezone *time.Location
|
||||
}
|
||||
|
||||
func (l *ScrobblerLog) Parse(data io.Reader, includeSkipped bool) error {
|
||||
|
@ -173,7 +175,6 @@ func (l *ScrobblerLog) ReadHeader(reader *bufio.Reader) error {
|
|||
timezone, found := strings.CutPrefix(text, "#TZ/")
|
||||
if found {
|
||||
l.TZ = TZInfo(timezone)
|
||||
l.location = locationFromTimezone(l.TZ)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -223,6 +224,11 @@ func (l ScrobblerLog) rowToRecord(row []string) (Record, error) {
|
|||
return record, err
|
||||
}
|
||||
|
||||
var timezone *time.Location = nil
|
||||
if l.TZ == TZ_UNKNOWN {
|
||||
timezone = l.FallbackTimezone
|
||||
}
|
||||
|
||||
record = Record{
|
||||
ArtistName: row[0],
|
||||
AlbumName: row[1],
|
||||
|
@ -230,7 +236,7 @@ func (l ScrobblerLog) rowToRecord(row []string) (Record, error) {
|
|||
TrackNumber: trackNumber,
|
||||
Duration: time.Duration(duration) * time.Second,
|
||||
Rating: Rating(row[5]),
|
||||
Timestamp: timeFromLocalTimestamp(timestamp, l.location),
|
||||
Timestamp: timeFromLocalTimestamp(timestamp, timezone),
|
||||
}
|
||||
|
||||
if len(row) > 7 {
|
||||
|
@ -240,26 +246,20 @@ func (l ScrobblerLog) rowToRecord(row []string) (Record, error) {
|
|||
return record, 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 TZInfo) *time.Location {
|
||||
location, err := time.LoadLocation(string(timezone))
|
||||
if err != nil {
|
||||
return time.UTC
|
||||
}
|
||||
return location
|
||||
}
|
||||
|
||||
// Convert a Unix timestamp to a time.Time object, but treat the timestamp
|
||||
// Convert a Unix timestamp to a [time.Time] object, but treat the timestamp
|
||||
// as being in the given location's timezone instead of UTC.
|
||||
// If location is nil, the timestamp is returned as 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)
|
||||
// The time is now in UTC. Get the offset to the requested timezone
|
||||
// and shift the time accordingly.
|
||||
if location != nil {
|
||||
_, offset := t.In(location).Zone()
|
||||
if offset != 0 {
|
||||
t = t.Add(time.Duration(offset) * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
|
|
@ -81,6 +81,21 @@ func TestParserExcludeSkipped(t *testing.T) {
|
|||
record4.MusicBrainzRecordingID)
|
||||
}
|
||||
|
||||
func TestParserFallbackTimezone(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
data := bytes.NewBufferString(testScrobblerLog)
|
||||
result := scrobblerlog.ScrobblerLog{
|
||||
FallbackTimezone: time.FixedZone("UTC+2", 7200),
|
||||
}
|
||||
err := result.Parse(data, false)
|
||||
require.NoError(t, err)
|
||||
record1 := result.Records[0]
|
||||
assert.Equal(
|
||||
time.Unix(1260342084, 0).Add(2*time.Hour),
|
||||
record1.Timestamp,
|
||||
)
|
||||
}
|
||||
|
||||
func TestAppend(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
data := make([]byte, 0, 10)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue