[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
Owner

📋 Pull Request Information

Original PR: https://github.com/advplyr/audiobookshelf/pull/5060
Author: @pwinnski
Created: 2/15/2026
Status: Closed

Base: masterHead: master


📝 Commits (1)

  • f29a177 Update 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. Now listeningStats separates the sessionTimeListening into day 1 and day 2. If the sessionTimeListening is the time between startedAt and updatedAt, then the seconds are allocated accurately. If updatedAt is longer from startedAt than sessionTimeListening, 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 sessionTimeListening is 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:

UPDATE playbackSessions SET createdAt = '2026-02-14 05:55:00.000 +00:00', updatedAt = '2026-02-14 06:00:30.000 +00:00', timeListening = 330 WHERE id = 'a6fd8a40-f273-445e-96b8-2c5bac507dd5';

I tested with sessions that began or ended exactly at midnight, 5, 30, and 60 seconds before and after, sessions in which timeListening was much shorter or longer than the actual gap between createdAt and updatedAt, 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.
image


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

## 📋 Pull Request Information **Original PR:** https://github.com/advplyr/audiobookshelf/pull/5060 **Author:** [@pwinnski](https://github.com/pwinnski) **Created:** 2/15/2026 **Status:** ❌ Closed **Base:** `master` ← **Head:** `master` --- ### 📝 Commits (1) - [`f29a177`](https://github.com/advplyr/audiobookshelf/commit/f29a1772be1fc3bedadf608a1999f16a509fae30) Update how getUserListeningStatsHelpers() handles playbackSessions that cross midnight ### 📊 Changes **1 file changed** (+46 additions, -9 deletions) <details> <summary>View changed files</summary> 📝 `server/routers/ApiRouter.js` (+46 -9) </details> ### 📄 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`. Now `listeningStats` separates the `sessionTimeListening` into day 1 and day 2. If the `sessionTimeListening` is the time between `startedAt` and `updatedAt`, then the seconds are allocated accurately. If `updatedAt` is longer from `startedAt` than `sessionTimeListening`, 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 `sessionTimeListening` is 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: ```sql UPDATE playbackSessions SET createdAt = '2026-02-14 05:55:00.000 +00:00', updatedAt = '2026-02-14 06:00:30.000 +00:00', timeListening = 330 WHERE id = 'a6fd8a40-f273-445e-96b8-2c5bac507dd5'; ``` I tested with sessions that began or ended exactly at midnight, 5, 30, and 60 seconds before and after, sessions in which `timeListening` was much shorter or longer than the actual gap between `createdAt` and `updatedAt`, 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. <img width="881" height="634" alt="image" src="https://github.com/user-attachments/assets/d83c33b0-ddb3-4a3d-9972-1bfc2dd00941" /> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
adam added the pull-request label 2026-04-25 00:19:37 +02:00
adam closed this issue 2026-04-25 00:19:37 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/audiobookshelf#4407