pyrochlore / obsidian-tracker

A plugin tracks occurrences and numbers in your notes
MIT License
1.29k stars 229 forks source link

Example sleep tracker doesn't work for sleep times before and after 00:00 (midnight) #295

Open ghost opened 8 months ago

ghost commented 8 months ago

Someone else posted about this on the Obsidian forum: https://forum.obsidian.md/t/custom-hour-shift-for-sleep-tracker/45928

It's an issue I've been trying to solve but don't know how. The example sleep tracker doesn't show times before and after midnight in a sensible way, and I'm not sure how to make it do that.

Expected Behavior

Say we have two sleep times, 23:30 (11:30pm) and 00:30 (12:30am). The tracker should display those an hour apart.

Current Behavior

The tracker currently shows those two sleep times as 23 hours apart, I think because it doesn't handle the notion of two different days.

Steps to Reproduce (for bugs)

Just run the example sleep tracker with those two sleep times.

Context

Unfortunately it makes my sleep tracker not very useful, since my sleep times are sometimes before and sometimes after midnight.

JameeKim commented 7 months ago

I encountered the same problem today. I was wondering if I should try to go to bed before midnight to make tracking easier. 😆 /j

TL;DR You could do one of:

  1. write your sleep times as something like -00:30 if before midnight, or
  2. create an auto-updated property field using another plugin which converts your sleep time into the above format.

What I realized was that using values like -01:30 made the chart render the way I wanted. If you're okay with using that notation in your notes, then it could be the way to go.

What I actually ended up doing involved another plugin called Metadata Menu. Using it, I set up an auto-updated property field in the frontmatter which converted my inputs into a format like [-00:30, 07:30] with the values representing the time differences from the midnight of the day for that note. I had to do this because I've been recording my times in the full datetime format. In case it helps anyone, below is the code snippet I used for the property's formula.

// My input fields are something like:
// [go-to-bed:: 2024-01-30T00:30]
// [wake-up:: 2024-01-30T07:30]
(() => {
const goToBed = current["go-to-bed"];
const wakeUp = current["wake-up"];
if (!goToBed || !wakeUp) return "";
const midnight = current.file.day;
const sleepTime = goToBed < midnight
  ? midnight.diff(goToBed).toFormat("-hh:mm")
  : goToBed.diff(midnight).toFormat("hh:mm");
const wakeUpTime = wakeUp.diff(midnight).toFormat("hh:mm");
return `[${sleepTime}, ${wakeUpTime}]`;
})()

If you're just recording times in formats like 23:00, then you just need to convert the sleep time and use the original field for the wake-up time. If you're using Metadata Menu, the formula would be something like below. (Disclaimer: I haven't tested the code)

// Let's say you have the field as:
// sleep:: 23:30/07:30
(() => {
const sleep = current.sleep?.split("/");
if (!sleep?.length) return "";
const sleepTime = dv.luxon.Duration.fromISOTime(sleep[0]);
// No change if before 12:00 (adjust as needed)
return sleepTime.hours < 12 ? sleep[0] : dv.luxon.Duration.fromObject({ hours: 24 }).minus(sleepTime).toFormat("-hh:mm");
})()

Then, you could use the new field in the tracker code block.

IIRC, a plugin called MetaEdit also allows you to create an auto-updated property field. I haven't used it yet, so I'm not sure how to get that working for this.

I hope this helps anyone reading this!