Found the solution, thanks for all your help everybody! I will be upfront with you I am VERY BAD at using most debugging tools and stepping through the program with stops, but I recently became decent at using the Logcat, so the way I debugged this was by drawing it out on pencil and paper and visually mapping out the relationships of my variables with a Timeline Diagram!
I was going to write down the numbers and everything, but just in drawing this, it occurred to me that to my astonishment, I didn't have too many variables (which is definitely the way it seems, trust me I know) I was actually MISSING an important variable! The "notification threshold" as it were, and the respective "daysBeforeExpMillis" to calculate it. Folks were pointing out the inconsistency between days notice on one hand vs. days before exp on the other hand which I admit is extremely confusing cause it sounds like "days_before_exp" should be calculated via the current time. In reality there are two time ranges/windows one is the days notice window which is the bigger one that is fixed and determined by the user. The other window is the "days_before_exp" according-to-your-reminders window, which is not fixed, but adjusts itself based on how close to expiration we are.
So the solution was to put back in my days_until_exp-setting if statement WITH this new notification threshold and then my notifications started behaving correctly:
Log.d("ITEM NAME:", "ITEM NAME: " + name);
String expDateString = item.getString("expDate");
Date expDate = sdf.parse(expDateString); // Set to end of day (23:59:59)
long expDateMillis = expDate.getTime();
int daysNotice = item.getInt("daysNotice");
long daysNoticeMillis = daysNotice * MILLIS_IN_A_DAY;
long expirationThreshold = expDateMillis - daysNoticeMillis;
long currentTimeMillis = System.currentTimeMillis();
if (currentTimeMillis < (expDateMillis - (14 * MILLIS_IN_A_DAY))) {
// Far from expiring (more than DAYS_BEFORE_EXPIRY days away) – schedule for 14 days before expiry.
DAYS_BEFORE_EXPIRY = 14;
} else if (currentTimeMillis < (expDateMillis - (7 * MILLIS_IN_A_DAY))) {
// Between 14 and 7 days before expiry – schedule for 7 days before expiry.
DAYS_BEFORE_EXPIRY = 7;
} else if (currentTimeMillis < (expDateMillis - (3 * MILLIS_IN_A_DAY))) {
// Between 7 and 3 days before expiry – schedule for 3 days before expiry.
DAYS_BEFORE_EXPIRY = 3;
} else if (currentTimeMillis < expirationThreshold) {
// Less than 3 days away but still before the user's notice threshold – schedule for 1 day before expiry.
}
**long daysBeforeExpMillis = (MILLIS_IN_A_DAY * DAYS_BEFORE_EXPIRY);**
**long notificationThreshold = expDateMillis - daysBeforeExpMillis;**
**notificationThreshold = expDateMillis - daysBeforeExpMillis;**
Log.d("EXP DATE MILLIS:", "EXP DATE MILLIS: " + String.valueOf(expDateMillis));
Log.d("DAYS NOTICE:", "DAYS NOTICE: " + String.valueOf(daysNotice));
Log.d("DAYS NOTICE:", "DAYS NOTICE MILLIS: " + String.valueOf(daysNoticeMillis));
Log.d("DAYS BEFORE EXP:", "DAYS BEFORE EXP: " + String.valueOf(DAYS_BEFORE_EXPIRY));
Log.d("DAYS BEFORE EXP:", "DAYS BEFORE EXP MILLIS: " + String.valueOf(daysBeforeExpMillis));
Log.d("NOTIFY TIME MILLIS:","NOTIFY TIME MILLIS: " + String.valueOf(notificationThreshold));
Here are my much cleaner logs that I was able to retrieve after debugging the issue:
2025-02-28 13:19:10.843 6370-6426 ITEM NAME: sma...tory.smartinventorywithsearch D ITEM NAME: Elder Scrolls V: Skyrim (Xbox 360 / PS3 / PC)
2025-02-28 13:19:10.843 6370-6370 AutofillManager sma...tory.smartinventorywithsearch D view not autofillable - not passing ime action check
2025-02-28 13:19:10.844 6370-6426 EXP DATE MILLIS: sma...tory.smartinventorywithsearch D EXP DATE MILLIS: 1741579200000
2025-02-28 13:19:10.845 6370-6426 DAYS NOTICE: sma...tory.smartinventorywithsearch D DAYS NOTICE: 100
2025-02-28 13:19:10.845 6370-6426 DAYS NOTICE: sma...tory.smartinventorywithsearch D DAYS NOTICE MILLIS: 8640000000
2025-02-28 13:19:10.845 6370-6426 DAYS BEFORE EXP: sma...tory.smartinventorywithsearch D DAYS BEFORE EXP: 7
2025-02-28 13:19:10.845 6370-6426 DAYS BEFORE EXP: sma...tory.smartinventorywithsearch D DAYS BEFORE EXP MILLIS: 604800000
2025-02-28 13:19:10.845 6370-6426 NOTIFY TIME MILLIS: sma...tory.smartinventorywithsearch D NOTIFY TIME MILLIS: 1740974400000
2025-02-28 13:19:10.845 6370-6426 Debug sma...tory.smartinventorywithsearch D Elder Scrolls V: Skyrim (Xbox 360 / PS3 / PC) will expire soon!
2025-02-28 13:19:10.846 6370-6426 Alarm sma...tory.smartinventorywithsearch D Scheduled notification for Elder Scrolls V: Skyrim (Xbox 360 / PS3 / PC) at 1740974400000
2025-02-28 13:19:10.846 6370-6426 ITEM NAME: sma...tory.smartinventorywithsearch D ITEM NAME: Irish Penny Whistle - Key Of D | Book | Condition Good
2025-02-28 13:19:10.847 6370-6426 EXP DATE MILLIS: sma...tory.smartinventorywithsearch D EXP DATE MILLIS: 1740546000000
2025-02-28 13:19:10.847 6370-6426 DAYS NOTICE: sma...tory.smartinventorywithsearch D DAYS NOTICE: 80
2025-02-28 13:19:10.847 6370-6426 DAYS NOTICE: sma...tory.smartinventorywithsearch D DAYS NOTICE MILLIS: 6912000000
2025-02-28 13:19:10.847 6370-6426 DAYS BEFORE EXP: sma...tory.smartinventorywithsearch D DAYS BEFORE EXP: 7
2025-02-28 13:19:10.847 6370-6426 DAYS BEFORE EXP: sma...tory.smartinventorywithsearch D DAYS BEFORE EXP MILLIS: 604800000
2025-02-28 13:19:10.847 6370-6426 NOTIFY TIME MILLIS: sma...tory.smartinventorywithsearch D NOTIFY TIME MILLIS: 1739941200000
2025-02-28 13:19:10.847 6370-6426 Debug sma...tory.smartinventorywithsearch D Irish Penny Whistle - Key Of D | Book | Condition Good has expired!
2025-02-28 13:19:10.848 6370-6426 Alarm sma...tory.smartinventorywithsearch D Scheduled notification for Irish Penny Whistle - Key Of D | Book | Condition Good at 1739941200000
2025-02-28 13:19:10.848 6370-6426 ITEM NAME: sma...tory.smartinventorywithsearch D ITEM NAME: coke
2025-02-28 13:19:10.849 6370-6426 EXP DATE MILLIS: sma...tory.smartinventorywithsearch D EXP DATE MILLIS: 1558324800000
2025-02-28 13:19:10.849 6370-6426 DAYS NOTICE: sma...tory.smartinventorywithsearch D DAYS NOTICE: 90
2025-02-28 13:19:10.849 6370-6426 DAYS NOTICE: sma...tory.smartinventorywithsearch D DAYS NOTICE MILLIS: 7776000000
2025-02-28 13:19:10.849 6370-6426 DAYS BEFORE EXP: sma...tory.smartinventorywithsearch D DAYS BEFORE EXP: 7
2025-02-28 13:19:10.849 6370-6426 DAYS BEFORE EXP: sma...tory.smartinventorywithsearch D DAYS BEFORE EXP MILLIS: 604800000
2025-02-28 13:19:10.849 6370-6426 NOTIFY TIME MILLIS: sma...tory.smartinventorywithsearch D NOTIFY TIME MILLIS: 1557720000000
2025-02-28 13:19:10.849 6370-6426 Debug sma...tory.smartinventorywithsearch D coke has expired!
2025-02-28 13:19:10.850 6370-6426 Alarm sma...tory.smartinventorywithsearch D Scheduled notification for coke at 1557720000000
2025-02-28 13:19:10.854 6370-6426 ITEM NAME: sma...tory.smartinventorywithsearch D ITEM NAME: Ratchet & Clank 2 for PlayStation 2
2025-02-28 13:19:10.855 6370-6426 EXP DATE MILLIS: sma...tory.smartinventorywithsearch D EXP DATE MILLIS: 1741064400000
2025-02-28 13:19:10.855 6370-6426 DAYS NOTICE: sma...tory.smartinventorywithsearch D DAYS NOTICE: 250
2025-02-28 13:19:10.855 6370-6426 DAYS NOTICE: sma...tory.smartinventorywithsearch D DAYS NOTICE MILLIS: 21600000000
2025-02-28 13:19:10.855 6370-6426 DAYS BEFORE EXP: sma...tory.smartinventorywithsearch D DAYS BEFORE EXP: 3
2025-02-28 13:19:10.855 6370-6426 DAYS BEFORE EXP: sma...tory.smartinventorywithsearch D DAYS BEFORE EXP MILLIS: 259200000
2025-02-28 13:19:10.855 6370-6426 NOTIFY TIME MILLIS: sma...tory.smartinventorywithsearch D NOTIFY TIME MILLIS: 1740805200000
2025-02-28 13:19:10.855 6370-6426 Debug sma...tory.smartinventorywithsearch D Ratchet & Clank 2 for PlayStation 2 will expire soon!
2025-02-28 13:19:10.858 6370-6426 Alarm sma...tory.smartinventorywithsearch D Scheduled notification for Ratchet & Clank 2 for PlayStation 2 at 1740805200000
...
2025-02-28 13:19:15.860 6370-6370 Notification sma...tory.smartinventorywithsearch D Notification received! // Irish Penny Whistle (expired)
2025-02-28 13:19:15.883 6370-6370 Notification sma...tory.smartinventorywithsearch D Notification received! // Coke (expired)
Now the notifications only fire prematurely if an item is already expired -which happens to be exactly the behavior I wanted anyway so it's a wrap! 😁
Again I really appreciate your folks' help, have a good one everybody!