bashawkformattingicalendar

Converting ICS Date to YYYY:MM:DD:HH:mm


I have this bash script that fetches calendar event data from a specified ICS (iCalendar) URL and displays events for the current date. The start and end of the events is displayed in the ics format. I have not idea how I can convert the ics format to the YYYY:MM:DD:HH:mm format.

Here is my script:

# Define the ICS URL of your calendar
ics_url="your_url"

# Get today's date in YYYYMMDD format
today=$(date +%Y%m%d)

# Use curl to fetch the ICS data and process it
curl -s "$ics_url" | awk -v date="$today" '
BEGIN {
    inEvent = 0;
    matched = 0;
    eventBuffer = "";
}
/BEGIN:VEVENT/ {
    inEvent = 1;
    matched = 0;
    eventBuffer = "";  # Reset event buffer at the beginning of a new event
}
/END:VEVENT/ {
    if (matched) {
        print eventBuffer;  # Print the event buffer if matched
        print "";  # Print an empty line after each event
    }
    inEvent = 0;
}
/^DTSTART:/ {
    if (index($0, date) > 0) {
        matched = 1;
    }
    # Replace "DTSTART" with "start"
    sub(/^DTSTART:/, "start:", $0);
    eventBuffer = eventBuffer "\n" $0;
}
/^DTEND:/ {
    # Replace "DTEND" with "end"
    sub(/^DTEND:/, "end:", $0);
    eventBuffer = eventBuffer "\n" $0;
}
/^SUMMARY|DESCRIPTION/ {
    eventBuffer = eventBuffer "\n" $0;
}
' 

Example output:

start:20240502T080000Z

end:20240502T090000Z

SUMMARY:Event

Desired output:

start:2024:05:02:08:00:00

end:2024:05:02:09:00:00

SUMMARY:Event

or

start:08:00

end:09:00

SUMMARY:Event

I found a solution. Thanks for all the answers. They helped a lot.

ics_url="your_url"

# Get today's date in YYYYMMDD format
today=$(date +%Y%m%d)

# Use curl to fetch the ICS data and process it
curl -s "$ics_url" | awk -v date="$today" '
BEGIN {
    inEvent = 0;
    matched = 0;
}
/BEGIN:VEVENT/ {
    inEvent = 1;
    matched = 0;  # Reset the matched flag at the beginning of a new event
    start = "";  # Reset variables at the start of a new event
    end = "";
    summary = "";
}
/END:VEVENT/ {
    if (matched) {
        # Extract hour and minute from start and end variables
        start1 = substr(start, 10, 2);
        start2 = substr(start, 12, 2);
        end1 = substr(end, 10, 2);
        end2 = substr(end, 12, 2);

        # Output the data in the specified order
        print "Event: " summary;
        print "start: " start1 ":" start2;
        print "end: " end1 ":" end2;
        print "";  # Print an empty line to separate events
    }
    inEvent = 0;
}
/^DTSTART:/ {
    if (index($0, date) > 0) {
        matched = 1;
    }
    # Store the start time without the label
    sub(/^DTSTART:/, "", $0);
    if (matched) {
        start = $0;
    }
}
/^DTEND:/ {
    # Store the end time without the label
    sub(/^DTEND:/, "", $0);
    if (matched) {
        end = $0;
    }
}
/^SUMMARY:/ {
    # Store the summary without the label
    sub(/^SUMMARY:/, "", $0);
    if (matched) {
        summary = $0;
    }
}'

New Output:

Event: Meeting
start: 10:30
end: 11:30

Event: Go for a walk
start: 10:00
end: 10:30

Solution

  • The following update should solve your requirement:

    # Define the ICS URL of your calendar
    ics_url="your_url"
    
    # Get today's date in YYYYMMDD format
    today=$(date +%Y%m%d)
    
    # Use curl to fetch the ICS data and process it
    curl -s "$ics_url" | awk -v date="$today" '
    BEGIN {
        inEvent = 0;
        matched = 0;
        eventBuffer = "";
    }
    /BEGIN:VEVENT/ {
        inEvent = 1;
        matched = 0;
        eventBuffer = "";  # Reset event buffer at the beginning of a new event
    }
    /END:VEVENT/ {
        if (matched) {
            print eventBuffer;  # Print the event buffer if matched
            print "";  # Print an empty line after each event
        }
        inEvent = 0;
    }
    /^DTSTART:/ {
        if (index($0, date) > 0) {
            matched = 1;
        }
        # Replace "DTSTART" with "start"
        t = mktime(substr($0,9,4) " " substr($0,13,2) " " substr($0,15,2) " " substr($0,18,2) " " substr($0,20,2) " " substr($0,22,2))
        line = "start:" strftime("%Y:%m:%d:%H:%M:%S",t)
        eventBuffer = eventBuffer "\nstart:" line;
    }
    /^DTEND:/ {
        # Replace "DTEND" with "end"
        t = mktime(substr($0,7,4) " " substr($0,11,2) " " substr($0,13,2) " " substr($0,16,2) " " substr($0,18,2) " " substr($0,20,2))
        line = strftime("%Y:%m:%d:%H:%M:%S",t)
        eventBuffer = eventBuffer "\nend:" line;
    }
    /^SUMMARY|DESCRIPTION/ {
        eventBuffer = eventBuffer "\n" $0;
    }
    '
    

    Testing with the following input:

    $ cat input.txt 
    BEGIN:VCALENDAR
    VERSION:2.0
    PRODID:-//Example Corp.//iCal4j 1.0//EN
    CALSCALE:GREGORIAN
    BEGIN:VEVENT
    DTSTAMP:20240502T120000Z
    DTSTART:20240505T090000Z
    DTEND:20240505T100000Z
    SUMMARY:Team Meeting
    DESCRIPTION:Weekly team meeting to discuss progress and upcoming tasks.
    LOCATION:Conference Room
    UID:1234567890
    SEQUENCE:0
    END:VEVENT
    BEGIN:VEVENT
    DTSTAMP:20240502T120000Z
    DTSTART:20240510T140000Z
    DTEND:20240510T160000Z
    SUMMARY:Client Presentation
    DESCRIPTION:Present our latest project updates to the client.
    LOCATION:Client's Office
    UID:0987654321
    SEQUENCE:0
    END:VEVENT
    END:VCALENDAR
    

    The output will be:

    start:start:2024:05:05:09:00:00
    end:2024:05:05:10:00:00
    SUMMARY:Team Meeting
    DESCRIPTION:Weekly team meeting to discuss progress and upcoming tasks.
    
    
    start:start:2024:05:10:14:00:00
    end:2024:05:10:16:00:00
    SUMMARY:Client Presentation
    DESCRIPTION:Present our latest project updates to the client.
    

    I ran it a little bit different ... I have the input as input.txt, the awk script as format.awk:

    BEGIN {
        inEvent = 0;
        matched = 0;
        eventBuffer = "";
    }
    /BEGIN:VEVENT/ {
        inEvent = 1;
        matched = 0;
        eventBuffer = "";  # Reset event buffer at the beginning of a new event
    }
    /END:VEVENT/ {
        if (matched) {
            print eventBuffer;  # Print the event buffer if matched
            print "";  # Print an empty line after each event
        }
        inEvent = 0;
    }
    /^DTSTART:/ {
        if (index($0, date) > 0) {
            matched = 1;
        }
        # Replace "DTSTART" with "start"
        t = mktime(substr($0,9,4) " " substr($0,13,2) " " substr($0,15,2) " " substr($0,18,2) " " substr($0,20,2) " " substr($0,22,2))
        line = "start:" strftime("%Y:%m:%d:%H:%M:%S",t)
        eventBuffer = eventBuffer "\nstart:" line;
    }
    /^DTEND:/ {
        # Replace "DTEND" with "end"
        t = mktime(substr($0,7,4) " " substr($0,11,2) " " substr($0,13,2) " " substr($0,16,2) " " substr($0,18,2) " " substr($0,20,2))
        line = strftime("%Y:%m:%d:%H:%M:%S",t)
        eventBuffer = eventBuffer "\nend:" line;
    }
    /^SUMMARY|DESCRIPTION/ {
        eventBuffer = eventBuffer "\n" $0;
    }
    

    And using CLI:

    awk -f format.awk input.txt