Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Last Played At: Add UI for last_played_at column #3457

Merged
merged 9 commits into from
Dec 28, 2020

Conversation

ywwg
Copy link
Member

@ywwg ywwg commented Dec 17, 2020

No description provided.

@ywwg ywwg requested a review from uklotzde December 17, 2020 00:50
@@ -386,15 +386,18 @@ void insertTrack(
query.bindValue(":bitrate", bitrate);
query.bindValue(":analyze_path", anlzPath);
query.bindValue(":device", device);
query.bindValue(":color", mixxx::RgbColor::toQVariant(colorFromID(static_cast<int>(track->color_id()))));
query.bindValue(":color",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the code formatter went to town on this file.

@@ -1093,6 +1189,9 @@ void RekordboxPlaylistModel::initSortColumnMapping() {
m_columnIndexBySortColumnId[static_cast<int>(
TrackModel::SortColumnId::TimesPlayed)] =
fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED);
m_columnIndexBySortColumnId[static_cast<int>(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here is the actual new code in this file

Copy link
Contributor

@uklotzde uklotzde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for finishing this feature! Code changes seem sensible, less than expected. Not yet test.

@uklotzde
Copy link
Contributor

Conflicts. Should be rebased after #3465 has been merged into main.

@uklotzde
Copy link
Contributor

Just one minor suggestion for renaming the column header. Otherwise ready to merge.

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The play column has an offset of UTC-Local Time.

In the sqlite file we use UTC to store the date added. That is OK to see a consecutive order independent of the time zones.

The last played column is stored in local time an I think the display code here assumes UTC, leading to the issue.

I am not DJing in different time Zones, but I can imagine that here is a use case of sorting the tracks by hour last played.
If I had a gig China for instance and back in Europa I see the tracks played at 14:00 MET which has been played in China at 22:00 local time, it will be confusing.

lt;dr:

Let's stick with storing local time and remove the offset for displaying here.

@@ -613,6 +618,7 @@ QVariant BaseTrackTableModel::roleValue(
return QString("(%1)").arg(timesPlayed);
}
case ColumnCache::COLUMN_LIBRARYTABLE_DATETIMEADDED:
case ColumnCache::COLUMN_LIBRARYTABLE_LAST_PLAYED_AT:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

COLUMN_LIBRARYTABLE_LAST_PLAYED_AT is not UTC. We need an extra case here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daschuer It actually is stored as UTC, so this code correct. Please double check!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, not with current upstream/main.

If we decide for UTC in the library, the code her is correct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot decide about this if the system already decided for us. At least for my setup the timestamps are stored in UTC (see comments).

@uklotzde
Copy link
Contributor

The play column has an offset of UTC-Local Time.

In the sqlite file we use UTC to store the date added. That is OK to see a consecutive order independent of the time zones.

The last played column is stored in local time an I think the display code here assumes UTC, leading to the issue.

I am not DJing in different time Zones, but I can imagine that here is a use case of sorting the tracks by hour last played.
If I had a gig China for instance and back in Europa I see the tracks played at 14:00 MET which has been played in China at 22:00 local time, it will be confusing.

lt;dr:

Let's stick with storing local time and remove the offset for displaying here.

CURRENT_TIMSTAMP generates an UTC timestamp for me. Please try this SELECT CURRENT_TIMSTAMP FROM library. If the behavior differs depending on the system configuration we are in big trouble.

@Holzhaus
Copy link
Member

I think @daschuer meant that we wants to store the local timezone the track was played in, not UTC. Personally I think if you travel a lot, it would be even more confusing if the last time played is ahead of your current local time. Therefore I think storing UTC makes sense and will probably save us a lot of headaches later on.

@daschuer
Copy link
Member

CURRENT_TIMSTAMP generates an UTC timestamp for me. Please try this SELECT CURRENT_TIMSTAMP FROM library. If the behavior differs depending on the system configuration we are in big trouble.

This works for me in UTC and is used for time added.

It looks like that the "last_played_at" column using local time, which is also OK for me.

I think @daschuer meant that we wants to store the local timezone the track was played in, not UTC.

It is already stored in local time. The issue her is that the displaying code assumes UTC and does a unnecessary and wrong conversion.

Personally I think if you travel a lot, it would be even more confusing if the last time played is ahead of your current local time.

Can this actually happen? How?

Therefore I think storing UTC makes sense and will probably save us a lot of headaches later on.

Yes, I think storing the value in UTC is reasonable, since all other times are also UTC. This is currently not the case.

If we only store UTC without the current Time zone. We can't do time only queries like "Tracks played at dinner timer" 18:00 - 21:00 or such. Because the dinner time in MET is not related to dinner time in CST.
I am unsure if this is a real use case though, but we have the chance to collect the data for future use.

A time zone field for each history playlist would be sufficient since it is unlikely that a DJ move the time zone during a gig.
On a cruise vessel maybe, but even then we don't want a gap/overlap when crossing a time zone.

@uklotzde
Copy link
Contributor

uklotzde commented Dec 23, 2020

I disagree. Storing plain UTC is valid and appropriate only for system-level events and as an optimization for sorting/ordering.

For user-level events that are often related to a geographical location you need to store local time with the time offset. This allows both, consistent ordering and meaningful display. Without the time offset (representing the time zone) you lose information!

This discussion is out of scope. Please report unambiguously what time is actually stored in your database and post an example timestamp. Please remember, for SQLite this is just plain text.

@Holzhaus
Copy link
Member

Personally I think if you travel a lot, it would be even more confusing if the last time played is ahead of your current local time.

Can this actually happen? How?

Yes, it can happen. Random example:

When the plane took off from Japan at 4:00 PM on October 24, it was 11 PM on October 23 in Los Angeles. Adding 9 and a half hours to this, the landing time would be 8:30 AM on October 24.

@uklotzde
Copy link
Contributor

uklotzde commented Dec 23, 2020

CURRENT_TIMESTAMP = '2020-12-21 17:35:48' generated and stored in UTC (system clock: UTC, display time zone: CET/GMT+01:00 with german locale settings)

@uklotzde
Copy link
Contributor

I suppose the content of pl_datetime_added depends on the system clock. This is unfortunate.

@daschuer
Copy link
Member

@uklotzde:

I disagree. Storing plain UTC is valid and appropriate only for system-level events and as an optimization for sorting/ordering.

I am not sure where you disagree to. We have here a bug that the time "last_played_at column" shows the wrong time, that is the root issue. What is your proposal to solve this?

@Holzhaus

Yes, it can happen. Random example:

When the plane took off from Japan at 4:00 PM on October 24, it was 11 PM on October 23 in Los Angeles. Adding 9 and a half hours to this, the landing time would be 8:30 AM on October 24.

Yes of cause. My considerations are if your did play a DJ gig just before and after start and the user expectationion when looking at a history playlist recorded in a different time zone.

But anyway, this would be "feature" of the history playlist. Here we are taking about last_played_at.

Please report unambiguously what time is actually stored in your database and post an example timestamp. Please remember, for SQLite this is just plain text.

In DB:
last_played_at:
2020-12-23T10:37:46.946
datetime_added:
2020-12-23T09:37:25.373Z

in GUI
Zeitstempel
23.12.20 10:37
Hinzugefügt
23.12.20 10:37
Last Played At
23.12.20 11:37 <- Wrong

@uklotzde
Copy link
Contributor

uklotzde commented Dec 23, 2020

#3477 tries to address the time zone confusions by relying on the DB for all the date/time formatting and simply copying the generated time stamps. Those values should only be read, but never written programmatically from C++. Otherwise we have to ensure that we are writing the exact same format as SQLite does.

@uklotzde
Copy link
Contributor

datetime_added:
2020-12-23T09:37:25.373Z

Is this really the exact column value in PlaylistTracks.pl_datetime_added? I get a different format, i.e. no ISO 8601.

@daschuer
Copy link
Member

2020-12-23T09:37:25.373Z is the value from library.datetime_added
2020-12-23 09:37:46 is the value from PlaylistTracks.pl_datetime_added
2020-12-23T10:37:46.946 is the value from library.last_played_at

All different formats :-/

@uklotzde
Copy link
Contributor

uklotzde commented Dec 23, 2020

library.datetime_added is generated by Mixxx. Using UTC is reasonable for this use case, although using local time + offset would be more appropriate and consistent.

PlaylistTracks.pl_datetime_added is generated by SQLite. It is UTC although the time zone is not specified. Moreover using UTC for the history playlists doesn't fit the use case as already discussed, local time + offset would be more appropriate.

library.last_played_at is parsed by Qt from SQLite and then stringified by Qt again. Since the SQLite timestamp (in UTC) doesn't mention a time zone Qt assumes local time which is wrong. Nevertheless writing another format than that generated by and copied from PlaylistTracks.pl_datetime_added mixes up the sorting in database queries.

@Be-ing
Copy link
Contributor

Be-ing commented Dec 23, 2020

IMO times should always be stored as UTC and transformed to local time when displayed to the user. This is simple and easy to keep correct.

@ywwg
Copy link
Member Author

ywwg commented Dec 23, 2020

IMO times should always be stored as UTC and transformed to local time when displayed to the user. This is simple and easy to keep correct.

completely agree -- DB times should all be UTC and adjusted for current local time. If that means someone gets on a plane and the times look wonky, so be it.

@ywwg
Copy link
Member Author

ywwg commented Dec 23, 2020

I think timestamp display issues are out of scope for this PR. This code displays the timestamp in a standard way, and that is good enough here. If we want to adjust the way we display times, let's do that in a followup

@daschuer
Copy link
Member

I think timestamp display issues are out of scope for this PR. This code displays the timestamp in a standard way, and that is good enough here. If we want to adjust the way we display times, let's do that in a followup

Unfortunately right now the bug is here. The time is read as UTC even though the library stores local time.

If you like to fix this this, It can be merged.

If we decide to change the time format in the library to UTC which seems to be reasonable, this can be done in this PR or in another PR that needs to be merged before this. In the later case this PR don't need to be changed.

If we change the time format we have the issue with alpha users. I think it is the best to deal with them by dropping the current column and create a new one.

Copy link
Contributor

@uklotzde uklotzde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ywwg Sorry for the noise. The bug is unrelated to this PR and must be fixed separately, i.e. by #3477.

Let's just merge this PR as is.

@uklotzde
Copy link
Contributor

@daschuer Please ignore the column values that are displayed after Mixxx has modified them. Instead re-execute the statement from schema migration 35 and then test if the values are displayed correctly. Anything else is out of scope right now.

Why should we delay this PR that only affects the display of those values?

@uklotzde
Copy link
Contributor

IMO times should always be stored as UTC and transformed to local time when displayed to the user. This is simple and easy to keep correct.

Using plain UTC for system time stamps and M2M communication is perfect. But it is inappropriate for many user-related use cases and especially contracts. I had to learn this after many years designing data models and interfaces for business services. The current local time zone is arbitrary and should not affect an event that happened in the past and that is associated with a place or geographical location.

@daschuer
Copy link
Member

After executing the migration statement the last_played_at column values are displayed correct with this branch.
All newly played tracks are displayed with an offset.

Why should we delay this PR that only affects the display of those values?

Because we than don't bother bleeding edge users with a broken feature. I would prefer to have it fixed before.
Since the feature can't be used right now, we have the option to move to a new column and not present users the mess we have produced since now.

The current local time zone is arbitrary and should not affect an event that happened in the past and that is associated with a place or geographical location.

I agree to that for the history view. This is an issue in the tracks table though, because we would have than Times from different time zones in on column. Do we agree that this should be transformed to local time?

@Holzhaus
Copy link
Member

This is an issue in the tracks table though, because we would have than Times from different time zones in on column. Do we agree that this should be transformed to local time?

We could work around that issue by displaying values like "5 minutes ago", "2 days ago", etc. Not sure if that is a good idea.

@daschuer
Copy link
Member

This will work for the major use case of finding tracks that have not been been played lets say since a year. For older tracks the wall clock time is not relevant.

I am still not clear if there is a use case for finding "dinner" or "late night" tracks. This sound appealing on the first sight, but is probably unreliable so that users better skim through there history itself. We have also crates for this.

What do you think?

@uklotzde
Copy link
Contributor

After executing the migration statement the last_played_at column values are displayed correct with this branch.
All newly played tracks are displayed with an offset.

Why should we delay this PR that only affects the display of those values?

Because we than don't bother bleeding edge users with a broken feature. I would prefer to have it fixed before.
Since the feature can't be used right now, we have the option to move to a new column and not present users the mess we have produced since now.

The current local time zone is arbitrary and should not affect an event that happened in the past and that is associated with a place or geographical location.

I agree to that for the history view. This is an issue in the tracks table though, because we would have than Times from different time zones in on column. Do we agree that this should be transformed to local time?

Due to lack of knowledge about the time zone or offset we are not able to migrate existing values. I am not investing any time on migrating to a new format. We only have to fix the different formats by storing all values in the SQLite-generated format consistently.

Displaying historic data transformed into the current local time zone is confusing. But since everything is stored in UTC we don't have a choice here and need to make a reasonable assumption. If you don't travel between different time zones frequently then the current local time zone is a good guess that should be valid for the majority of users.

@uklotzde
Copy link
Contributor

@ywwg Please review ywwg#10

An ugly workaround to bridge the gaps. The handling of date/time values from the database through the caching layer is brittle and inconsistent, much worse than what I expected. Take it or leave it.

@uklotzde
Copy link
Contributor

uklotzde commented Dec 25, 2020

ywwg#10 also splits the database migration to clean up the inconsistent values that have emerged until now.

@daschuer
Copy link
Member

Thank you very much @uklotzde ywwg#10 does the trick and solved the issue completely for me.
@ywwg Once you have merged it, this PR can be merged to finally enable the feature for alpha users.

@github-actions github-actions bot added the build label Dec 28, 2020
@daschuer
Copy link
Member

Thank you for joining forces :-)
LGTM.

@daschuer daschuer merged commit 8ba1a80 into mixxxdj:main Dec 28, 2020
@mixxxbot mixxxbot mentioned this pull request Aug 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

5 participants