andrewbrereton / obsidian-to-ical-plugin

This is a plugin for Obsidian that searches your vault for tasks that contain dates, and generates a calendar in iCal format that can be imported into your preferred calendar application.
MIT License
56 stars 10 forks source link

All schedules generated by plugin start from 00 : 00 #89

Open cllyreforce opened 2 months ago

cllyreforce commented 2 months ago

All schedules generated by plugin start from 00 : 00 ,i have write time ues the format HH:mm in the task ,but all schedules start from 00:00

RaffTechAU commented 1 month ago

This is happening for me as well.

Creating the task: - [ ] 08:00 - 10:00 This is a test ⏳ 2024-07-23 Results in the below ical properties: DTSTAMP:20240723T000000 DTSTART:20240723

The time is being lost somehow.

ChrisRule01 commented 1 month ago

Same when I create a task - [ ] 9:30 - 10:30 Test ⏳ 2024-07-31 and push it to my gist the Ical properties state:

BEGIN:VEVENT DTSTAMP:20240731T000000 DTSTART:20240731 SUMMARY:🔲 09:30 - 10:30 Test END:VEVENT

I have Day Planner enabled and checked the integration option in the Obsidian to ical plugin. When I open my daily note and type in the same thing as above (- [ ] 9:30 - 10:30 Test ⏳ 2024-07-31) the Day Planner recognizes it.

JeffeyChou commented 1 month ago

Hi everyone, I fixed this problem by modifying the source code in main.js

At line 4000 or so, add method after the var Task = class:

getTimeFromSummary() {
    const timeRegex = /(\d{2}:\d{2})(?:\s*-\s*(\d{2}:\d{2}))?/;
    const match = this.summary.match(timeRegex);
    if (match) {
      let start = match[1];
      let end = match[2] || match[1];

      // If start and end are the same, move end back half an hour
      if (start === end) {
        const [hours, minutes] = start.split(':').map(Number);
        const endDate = new Date();
        endDate.setHours(hours, minutes);
        endDate.setMinutes(endDate.getMinutes() + 30);

        const endHours = String(endDate.getHours()).padStart(2, '0');
        const endMinutes = String(endDate.getMinutes()).padStart(2, '0');
        end = `${endHours}:${endMinutes}`;
      }

      return {
        start: start,
        end: end
      };
    }
    return null;
  }

at line about 3843, modify the code into this:

   /* keep the code unchanged */
    getEvent(task, date, prependSummary) {
    if (task.hasAnyDate() === false) {
      return "";
    }
    let event = "BEGIN:VEVENT\r\nUID:" + task.getId() + "\r\nDTSTAMP:" + task.getDate(null, "YYYYMMDDTHHmmss") + "\r\n";

    const times = task.getTimeFromSummary();

    if (date === null ) {
      if (times) {
        const dtstart = task.getDate("Scheduled" /* Scheduled */, "YYYYMMDD");
        const dtend = task.getDate("Due" /* Due */, "YYYYMMDD");
        event += `DTSTART:${dtstart}T${times.start.replace(":", "")}00\r\n`;
        if (dtend) {
          event += `DTEND:${dtend}T${times.end.replace(":", "")}00\r\n`;
        } else {
          event += `DTEND:${dtstart}T${times.end.replace(":", "")}00\r\n`;
        }
      } else {
        switch (settings.howToProcessMultipleDates) {
          case "PreferScheduledDate":
            if (task.hasA("Scheduled" /* Scheduled */)) {
              event += "DTSTART:" + task.getDate("Scheduled" /* Scheduled */, "YYYYMMDDTHHmmss") + "\r\n";
            } else if (task.hasA("Due" /* Due */)) {
              event += "DTSTART:" + task.getDate("Due" /* Due */, "YYYYMMDDTHHmmss") + "\r\n";
            } else if (task.hasA("TimeStart" /* TimeStart */) && task.hasA("TimeEnd" /* TimeEnd */)) {
              event += "DTSTART:" + task.getDate("TimeStart" /* TimeStart */, "YYYYMMDD[T]HHmmss[Z]") + "\r\n";
              event += "DTEND:" + task.getDate("TimeEnd" /* TimeEnd */, "YYYYMMDD[T]HHmmss[Z]") + "\r\n";
            } else {
              event += "DTSTART:" + task.getDate(null, "YYYYMMDDTHHmmss") + "\r\n";
            }
            break;
          case "CreateMultipleEvents":
            event = "";
            if (task.hasA("Start" /* Start */)) {
              event += this.getEvent(task, task.getDate("Start" /* Start */, "YYYYMMDDTHHmmss"), "\u{1F6EB} ");
            }
            if (task.hasA("Scheduled" /* Scheduled */)) {
              event += this.getEvent(task, task.getDate("Scheduled" /* Scheduled */, "YYYYMMDDTHHmmss"), "\u23F3 ");
            }
            if (task.hasA("Due" /* Due */)) {
              event += this.getEvent(task, task.getDate("Due" /* Due */, "YYYYMMDDTHHmmss"), "\u{1F4C5} ");
            }
            if (event === "") {
              event += this.getEvent(task, task.getDate(null, "YYYYMMDDTHHmmss"), "");
            }
            return event;
          case "PreferDueDate":
            if (task.hasA("Scheduled" /* Scheduled */) && task.hasA("Due" /* Due */)) {
              event += "DTSTART:" + task.getDate("Scheduled" /* Scheduled */, "YYYYMMDDTHHmmss") + "\r\nDTEND:" + task.getDate("Due" /* Due */, "YYYYMMDDTHHmmss") + "\r\n";
            } else if (task.hasA("Due" /* Due */)) {
              event += "DTSTART:" + task.getDate("Due" /* Due */, "YYYYMMDDTHHmmss") + "\r\n";
            } else if (task.hasA("Scheduled" /* Scheduled */)) {
              event += "DTSTART:" + task.getDate("Scheduled" /* Scheduled */, "YYYYMMDDTHHmmss") + "\r\n";
            } else if (task.hasA("TimeStart" /* TimeStart */) && task.hasA("TimeEnd" /* TimeEnd */)) {
              event += "DTSTART:" + task.getDate("TimeStart" /* TimeStart */, "YYYYMMDD[T]HHmmss[Z]") + "\r\n";
              event += "DTEND:" + task.getDate("TimeEnd" /* TimeEnd */, "YYYYMMDD[T]HHmmss[Z]") + "\r\n";
            } else {
              event += "DTSTART:" + task.getDate(null, "YYYYMMDDTHHmmss") + "\r\n";
            }
            break;
        }
      }

    } else {
      if (times) {
        event += `DTSTART:${date.slice(0, 8)}T${times.start.replace(":", "")}00\r\n`;
        event += `DTEND:${date.slice(0, 8)}T${times.end.replace(":", "")}00\r\n`;
        event += `times:${times}\r\n`;
      } else {
        event += `DTSTART:${date}\r\n`;
      }
    }

    event += "SUMMARY:" + prependSummary + task.getSummary() + '\r\nLOCATION:ALTREP="' + encodeURI(task.getLocation()) + '":' + encodeURI(task.getLocation()) + "\r\nEND:VEVENT\r\n";
    return event;
  }

  getToDos(tasks) {
  /* keep the code unchanged */

and now this plugin recognize the Day planner format by default.

The generated .ics file looks like this:

  BEGIN:VEVENT
UID:465760d5-9b30-458a-aaf0-e1eb5fe240b3
DTSTAMP:20240801T000000
DTSTART:20240801T222300
DTEND:20240801T225500
SUMMARY:🔲 22:23 - 22:55 test
END:VEVENT
BEGIN:VEVENT
UID:e3f80dd8-ee1a-4b69-bfb5-462346dcade3
DTSTAMP:20240801T000000
DTSTART:20240801T223000
DTEND:20240801T230000
SUMMARY:🔲 22:30 test 🔽

I'm considering make a pull request, but I dont know how to test my code in my forked repo...Can anyone tell me how to do?

ChrisRule01 commented 1 month ago

Thanks for the source code @JeffeyChou. I implemented your code into my Obsidian Vault and it mostly works around (85% of the time for my tasks). However, the code seems to not recognize events before 10:00am. Example:

BEGIN:VEVENT DTSTAMP:20240804T000000 DTSTART:20240804T100000 DTEND:20240804T103000 SUMMARY:🔲 10:00 Water Plant #Weekly END:VEVENT

vs.

BEGIN:VEVENT DTSTAMP:20240804T000000 DTSTART:20240804T000000 SUMMARY:🔲 9:30 Weekly Journal #Weekly

I did some debugging on the source code (main.js) in the plugin itself and to fix this you need to change the line right after function getTimeFromSummary():

const timeRegex = /(\d{2}:\d{2})(?:\s-\s(\d{2}:\d{2}))?/;

to

const timeRegex = /(\d{1,2}:\d{2})(?:\s-\s(\d{1,2}:\d{2}))?/

Now it works for me on 100% of the cases.

JeffeyChou commented 1 month ago

Thanks for the source code @JeffeyChou. I implemented your code into my Obsidian Vault and it mostly works around (85% of the time for my tasks). However, the code seems to not recognize events before 10:00am. Example:

BEGIN:VEVENT DTSTAMP:20240804T000000 DTSTART:20240804T100000 DTEND:20240804T103000 SUMMARY:🔲 10:00 Water Plant #Weekly END:VEVENT

vs.

BEGIN:VEVENT DTSTAMP:20240804T000000 DTSTART:20240804T000000 SUMMARY:🔲 9:30 Weekly Journal #Weekly

I did some debugging on the source code (main.js) in the plugin itself and to fix this you need to change the line right after function getTimeFromSummary():

const timeRegex = /(\d{2}:\d{2})(?:\s-\s(\d{2}:\d{2}))?/;

to

const timeRegex = /(\d{1,2}:\d{2})(?:\s-\s(\d{1,2}:\d{2}))?/

Now it works for me on 100% of the cases.

Hi @ChrisRule01 , thank you for your kind reminder! I noticed such bugs in my test file, I make a more general timeRegex and it works.

The problem you mentioned lies in that the original Regex can't recognize AM/PM format, I make adjustment in my code, and make a pull request to this repo. It should work now.