mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-05-30 23:40:40 +02:00
[PR #5060] [CLOSED] Update how getUserListeningStatsHelpers() handles playbackSessions that cross midnight #4407
Closed
opened 2026-04-25 00:19:37 +02:00 by adam
·
0 comments
No Branch/Tag Specified
master
book_tags_genres_dedupe
episode_download_fallback
Issue-4540-SortBy-StartedDate-and-FinishedDate
episode_meta_tagging
fix_authorize_race_condition
redirect_transcode_requests
progress_updated_sort
fix_ereader_socket_event
fix_change_empty_root_password
fix_podcast_session_track_index
fix_set_token
session_modal_user
localize_durations
fix_oidc_create_user
jwt_auth_refactor
fix_scanner_deleting_single_file_books
fix_mediaprogress_updatedat_2
experimental_next_client
podcast_episode_duration
episode-timestamps-clickable
book_author_secondary_sort_title
podcast_useragents
pathexists_user_access
fix_pathexists_join
book_author_secondary_sort
clean_duplicate_mediaprogress
sanitize_html_description
trix_prevent_attachments
check_path_api_fix
fix_mediaprogress_updatedat
increase_express_json_limit
fix_dockerfile_nunicode
search_episodes
audiobook_tools_update
episode_secondary_sorts
hls_stream_url_update
new_session_track_endpoint
audiobook_tools_enhancements
watcher_rescans_update
player_track_tooltip
fix_exclude_prefixes_crash
socket_item_events
fix_podcast_episode_scanner_promise
new_stats_controller
count_cache_for_userpermissions
parsing-opf-v3
validate_migration_files
fix-quick-match-all-crash
fix-chapter-end-sleep-timer
stringify_sequelize_query
remove-col-ambiguity
fix_next_prev_edit_description
details_trim_whitespace
fix_content_url_basepath
fix_logger_fatal
progress_bar_visibility
batch-edit-populate-map-details
feed_generator_updates
bookmark-modal-updates
migrate-library-item-in-scanner
migrate-new-library-items
migrate-podcasts-new-library-item-2
migrate-podcasts-new-library-item
fix-remove-episode-from-playlist
playback-session-use-new-library-item
refactor-library-item
fix-heatmap-caption
feed-episodes-upsert
share-media-player-media-session-api
remove-old-playlist
remove_old_collection_object
plugin-implementation-demo
feed_migration
refactor-feeds-from-item
fix_remove_authors_no_books
v2.17.3-fk-constraints-migration
migrations-first-upgrade
sqlite_2
feature/nuxt-target-server
waveform
sqlite
playlists
video
v2.35.1
v2.35.0
v2.34.0
v2.33.2
v2.33.1
v2.33.0
v2.32.1
v2.32.0
v2.31.0
v2.30.0
v2.29.0
v2.28.0
v2.27.0
v2.26.3
v2.26.2
v2.26.1
v2.26.0
v2.25.1
v2.25.0
v2.24.0
v2.23.0
v2.22.0
v2.21.0
v2.20.0
v2.19.5
v2.19.4
v2.19.3
v2.19.2
v2.19.1
v2.19.0
v2.18.1
v2.18.0
v2.17.7
v2.17.6
v2.17.5
v2.17.4
v2.17.3
v2.17.2
v2.17.1
v2.17.0
v2.16.2
v2.16.1
v2.16.0
v2.15.1
v2.15.0
v2.14.0
v2.13.4
v2.13.3
v2.13.2
v2.13.1
v2.13.0
v2.12.3
v2.12.2
v2.12.1
v2.12.0
v2.11.0
v2.10.1
v2.10.0
v2.9.0
v2.8.1
v2.8.0
v2.7.2
v2.7.1
v2.7.0
v2.6.0
v2.5.0
v2.4.4
v2.4.3
v2.4.2
v2.4.1
v2.4.0
v2.3.5
v2.3.4
v2.3.3
v2.3.2
v2.3.1
v2.3.0
v2.2.23
v2.2.22
v2.2.21
v2.2.20
v2.2.19
v2.2.18
v2.2.17
v2.2.16
v2.2.15
v2.2.14
v2.2.13
v2.2.12
v2.2.11
v2.2.10
v2.2.9
v2.2.8
v2.2.7
v2.2.6
v2.2.5
v2.2.4
v2.2.3
v2.2.2
v2.2.1
v2.2.0
v2.1.5
v2.1.4
v2.1.3
v2.1.2
v2.1.1
v2.1.0
v2.0.24
v2.0.23
v2.0.22
v2.0.21
v2.0.20
v2.0.19
v2.0.18
v2.0.17
v2.0.16
v2.0.15
v2.0.14
v2.0.13
v2.0.12
v2.0.11
v2.0.10
v2.0.9
v2.0.8
v2.0.7
v2.0.6
v2.0.5
v2.0.4
v2.0.3
v2.0.2
v2.0.1
v1.7.2
v1.7.1
v1.7.0
v1.6.0
v1.5.5
v1.5.0
v1.4.11
v1.4.9
v1.4.7
v1.4.6
v1.4.4
v1.4.2
v1.4.0
v1.4.1
v1.3.4
v1.3.3
v1.3.1
v1.2.8
v1.2.6
v1.2.5
v1.2.4
v1.2.1
v1.1.15
v1.1.14
v1.1.13
v1.1.12
v1.1.11
v1.1.10
v1.1.9
v1.1.8
v1.0.0
0.9.61-beta.0
0.9.61-beta
Labels
Clear labels
authentication
backlog
bug
chapter editor
config-issue
ebooks
encoding/embedding
enhancement
help wanted
listening sessions & progress
planned
possible plugin
progress sync
pull-request
sorting/filtering/searching
unable to reproduce
upload
users & permissions
waiting
Mirrored from GitHub Pull Request
No Label
pull-request
Milestone
No items
No Milestone
Projects
Clear projects
No project
Assignees
adam (Adam Melkus)
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: starred/audiobookshelf#4407
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/advplyr/audiobookshelf/pull/5060
Author: @pwinnski
Created: 2/15/2026
Status: ❌ Closed
Base:
master← Head:master📝 Commits (1)
f29a177Update how getUserListeningStatsHelpers() handles playbackSessions that cross midnight📊 Changes
1 file changed (+46 additions, -9 deletions)
View changed files
📝
server/routers/ApiRouter.js(+46 -9)📄 Description
Brief summary
Improves the "Your Stats" page in cases when listening sessions cross midnight, reducing the chance of broken listening streaks.
Which issue is fixed?
Fixes #5059 and addresses/possibly-fixes #1445
In-depth Description
When playback sessions begin before midnight and end after midnight, they are counted as entirely taking place after midnight on the "Your Stats" page, so the 7-day chart shows 0 minutes on the day the session starts and more minutes on the day the session ended. If the session started on a day with no other sessions, the "days in a row" stat resets to 0. There have been other issues created for related issues, all based on the fact that playback sessions are counted as having taken place entire on one day.
This PR doesn't change the sessions, only
listeningStats. NowlisteningStatsseparates thesessionTimeListeninginto day 1 and day 2. If thesessionTimeListeningis the time betweenstartedAtandupdatedAt, then the seconds are allocated accurately. IfupdatedAtis longer fromstartedAtthansessionTimeListening, due to pauses or connection issues or client behaviors, then the seconds allocated proportionately, except that the start date is given at least 60 seconds if the session started at least 60 seconds before midnight.The previous logic is unchanged, only moved into a conditional block when the start date is the same as the session date.
If the two dates are different, then
sessionTimeListeningis split between day1 and day2 based on midnight in the server timezone. Most of the time, day1 will be the immediately previous day, but if not, then intermediate days are ignored and day1 is the first day, while day2 is the last day.It is possible to come up with edge cases that still deliver odd results, but the majority of cases that have been identified as dupes of #1445 are handled better, and none are handled worse.
How have you tested this?
I used devContainers and created sessions both using direct playback in the web interface and also via a mobile client (Prologue). I then used sqlite3 commands to update a single playback session, stopping and restarting the dev server each time, using both console.log() statements and refreshing the Your Stats page to see the effects. An example SQL update:
I tested with sessions that began or ended exactly at midnight, 5, 30, and 60 seconds before and after, sessions in which
timeListeningwas much shorter or longer than the actual gap betweencreatedAtandupdatedAt, and so on. I tested different days of the week, including exactly 7 days ago, and ensured the results are always at least as good as the current release, but better, since streaks aren't broken unnecessarily.Screenshots
No client changes, but here's a screenshot of the Your Stats page I took during testing.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.