Giter VIP home page Giter VIP logo

Comments (6)

fj avatar fj commented on July 17, 2024 2

👍 for this request. However, one clarification: the ...Thh:mm+xx:yy-notation doesn't support adding time zones, it supports adding time offsets. Those are very different things. There are many zones with the same offset, and every zone can use more than one offset.

For example, U.S. Eastern Time is a time zone that maps different points in time to different time offsets: -4 UTC in the summer, -5 UTC in the winter. But there are plenty of other time zones with the offset -5 UTC (for example, US Central Time is -5 UTC in the summer). The events API in GCal supports adding either a time zone or a time offset, but you almost always want a zone, not an offset.

from gcalcli.

tresni avatar tresni commented on July 17, 2024

You can specify a timezone in the --when option (e.g. --when 2007-09-24T15:30-8:00), both dateutil and parsedatetime should be able to deal with that. Given we only allow duration and not a specific end time, I'm not sure what the use case is here. Are you wanting an --until option instead of just --duration?

from gcalcli.

bekoeppel avatar bekoeppel commented on July 17, 2024

Hi

When I use --when '2013-03-11T9:30-8:00' --duration 60, the following event is created:

  • Start Time: 18:30
  • End Time: 19:30
  • Time Zone: +1:00 (my local time zone)

It looks like gcalcli is converting the specified time into my local time zone.

I would expect that the following event was created:

  • Start Time: 9:30
  • End Time: 10:30
  • Time Zone: -8:00 (time zone as specified)

I want to do this because I'm travelling for example to the US and will need to send the event as meeting invite to colleagues. I want that these invites are in the proper time zone.

Also, the --until parameter would be really nice, especially if it allowed me to specify a time zone as well (potentially a different time zone than in --when).

Benedikt

from gcalcli.

ac4000 avatar ac4000 commented on July 17, 2024

The following code should enable --until functionality. Once the time zone issue is sorted, --until should make it possible to have events start in one time zone and end in another. It would also be useful to avoid calculating the duration of events where the end time, not duration, is known. The --until argument overrides --duration if both are supplied. The changes are based on version 4.0.4-2 from the Debian 10 repos. If there's interest, I can try to find some time to clean it up and submit the code, but it might be better if someone more familiar with gcalcli and python does that.

diff -r -U0 ./argparsers.py /usr/lib/python3/dist-packages/gcalcli/argparsers.py
--- ./argparsers.py	2019-04-24 16:46:16.000000000 -0700
+++ /usr/lib/python3/dist-packages/gcalcli/argparsers.py	2021-06-20 14:43:32.938992990 -0700
@@ -301,0 +302 @@
+    add.add_argument('--until', default=None, type=str, help='Event end time (overrides --duration)')

diff -r -U0 ./cli.py /usr/lib/python3/dist-packages/gcalcli/cli.py
--- ./cli.py	2019-02-25 23:20:19.000000000 -0800
+++ /usr/lib/python3/dist-packages/gcalcli/cli.py	2021-06-20 14:34:12.832825535 -0700
@@ -70,6 +70,7 @@
-    if parsed_args.duration is None:
-        if parsed_args.allday:
-            prompt = 'Duration (days): '
-        else:
-            prompt = 'Duration (minutes): '
-        parsed_args.duration = get_input(printer, prompt, STR_TO_INT)
+    if parsed_args.until is None:
+        if parsed_args.duration is None:
+            if parsed_args.allday:
+                prompt = 'Duration (days): '
+            else:
+                prompt = 'Duration (minutes): '
+            parsed_args.duration = get_input(printer, prompt, STR_TO_INT)
@@ -181,10 +182,21 @@
-            try:
-                estart, eend = utils.get_times_from_duration(
-                        parsed_args.when, parsed_args.duration,
-                        parsed_args.allday
-                )
-            except ValueError as exc:
-                printer.err_msg(str(exc))
-                # Since we actually need a valid start and end time in order to
-                # add the event, we cannot proceed.
-                raise
+            if parsed_args.until is None:
+                try:
+                    estart, eend = utils.get_times_from_duration(
+                            parsed_args.when, parsed_args.duration,
+                            parsed_args.allday
+                    )
+                except ValueError as exc:
+                    printer.err_msg(str(exc))
+                    # Since we actually need a valid start and end time in order to
+                    # add the event, we cannot proceed.
+                    raise
+            else:
+                try:
+                    estart, eend = utils.get_times_from_until(
+                            parsed_args.when, parsed_args.until
+                    )
+                except ValueError as exc:
+                    printer.err_msg(str(exc))
+                    # Since we actually need a valid start and end time in order to
+                    # add the event, we cannot proceed.
+                    raise

diff -r -U0 ./utils.py /usr/lib/python3/dist-packages/gcalcli/utils.py
--- ./utils.py	2019-02-25 23:20:19.000000000 -0800
+++ /usr/lib/python3/dist-packages/gcalcli/utils.py	2021-06-20 14:36:57.392792278 -0700
@@ -66,0 +67,18 @@
+def get_times_from_until(when, until):
+
+    try:
+        start = get_time_from_str(when)
+    except Exception:
+        raise ValueError('Date and time is invalid: %s\n' % (when))
+
+    try:
+        stop = get_time_from_str(until)
+    except Exception:
+        raise ValueError('Date and time is invalid: %s\n' % (until))
+
+    start = start.isoformat()
+    stop = stop.isoformat()
+
+    return start, stop
+
+

from gcalcli.

ac4000 avatar ac4000 commented on July 17, 2024

Re the time zones, it appears that somewhere along the line, the supplied time zone info. is either getting mangled or dropped, possible at the parser, which may be returning a naive datetime object. Rather than get into that, I added two more parameters, --starttz and --endtz. This works just as well for my use cases. (It would be nice to parse the date input correctly, but for the few of us who need time zone functionality, we're probably happy enough to use the extra parameters.) The information supplied must be in a format the Google Calendar API can understand, but I'd recommend using IDs, like America/New_York, rather than offsets. So, e.g., incorporating --until, from above:

gcalcli ... --when '2021-06-21 1000' --until '2021-06-21 1930' --starttz 'America/New_York' --endtz 'Europe/London'

This diff is against the version as modified above (i.e., --until already included):

diff -U0 -r /tmp/gcalcli_2021-06-20/argparsers.py ./argparsers.py
--- /tmp/gcalcli_2021-06-20/argparsers.py	2021-06-20 14:43:32.000000000 -0700
+++ ./argparsers.py	2021-06-20 16:41:27.000000000 -0700
@@ -302,0 +303,2 @@
+    add.add_argument('--starttz', default=None, type=str, help='Event start time zone (Google Calendar API compatible format)')
+    add.add_argument('--endtz', default=None, type=str, help='Event end time zone (Google Calendar API compatible format)')

diff -U0 -r /tmp/gcalcli_2021-06-20/cli.py ./cli.py
--- /tmp/gcalcli_2021-06-20/cli.py	2021-06-20 14:34:12.000000000 -0700
+++ ./cli.py	2021-06-20 17:54:45.000000000 -0700
@@ -38,0 +39 @@
+from datetime import datetime
@@ -203,0 +205,8 @@
+            # strip time zone info if starttz or endtz supplied, but supply T so Google is happy
+            if parsed_args.starttz is not None:
+                estart_notz = datetime.strptime(estart, "%Y-%m-%dT%H:%M:%S%z").replace(tzinfo=None)
+                estart = str(estart_notz).replace(' ', 'T')
+            if parsed_args.endtz is not None:
+                eend_notz = datetime.strptime(eend, "%Y-%m-%dT%H:%M:%S%z").replace(tzinfo=None)
+                eend = str(eend_notz).replace(' ', 'T')
+
@@ -206 +215,2 @@
-                          parsed_args.reminders, parsed_args.event_color)
+                          parsed_args.reminders, parsed_args.event_color,
+                          parsed_args.starttz, parsed_args.endtz)

diff -U0 -r /tmp/gcalcli_2021-06-20/gcal.py ./gcal.py
--- /tmp/gcalcli_2021-06-20/gcal.py	2019-04-24 16:46:16.000000000 -0700
+++ ./gcal.py	2021-06-20 17:05:38.000000000 -0700
@@ -1269 +1269 @@
-    def AddEvent(self, title, where, start, end, descr, who, reminders, color):
+    def AddEvent(self, title, where, start, end, descr, who, reminders, color, starttz=None, endtz=None):
@@ -1284,4 +1284,12 @@
-            event['start'] = {'dateTime': start,
-                              'timeZone': self.cals[0]['timeZone']}
-            event['end'] = {'dateTime': end,
-                            'timeZone': self.cals[0]['timeZone']}
+            if starttz is None:
+                event['start'] = {'dateTime': start,
+                                  'timeZone': self.cals[0]['timeZone']}
+            else:
+                event['start'] = {'dateTime': start,
+                                  'timeZone': starttz}
+            if endtz is None:
+                event['end'] = {'dateTime': end,
+                                'timeZone': self.cals[0]['timeZone']}
+            else:
+                event['end'] = {'dateTime': end,
+                                'timeZone': endtz}

from gcalcli.

ac4000 avatar ac4000 commented on July 17, 2024

Again, building on the prior changes, the following allows you to retrieve the actual datetime values as Start: and End:, by supplying "start" and "end" under --details. Should now calculate Length: correctly as well, accounting for time zones. May require the --military parameter. If the time zone is not set correctly in the actual calendar event, "None" is displayed instead of the time zone. Note that the first line of output from search displays time in local time (however that's divined), so ignore that if you're parsing output and use Start: and End: instead.

Sample output from made-up flights (yeah, MAD-DEL is the scenic route):

# gcalcli search 'flight' --details start --details end --military

2021-06-23  16:04  IAD-MAD (AAL 1234; XF4GRK; A321)
                     Start: 2021-06-23 16:04 (EDT; UTC-0400)
                     End: 2021-06-23 17:22 (None; UTC+0200)
                      
2021-06-24  06:00  MAD-BOM (MAD 1235; XF4GRK; A346)
                     Start: 2021-06-24 12:00 (CEST; UTC+0200)
                     End: 2021-06-25 13:00 (IST; UTC+0530)
diff -U0 -r /tmp/gcalcli_2021-06-21/argparsers.py ./argparsers.py
--- /tmp/gcalcli_2021-06-21/argparsers.py	2021-06-20 16:41:27.000000000 -0700
+++ ./argparsers.py	2021-06-20 21:21:48.000000000 -0700
@@ -11 +11 @@
-           'url', 'attendees', 'email', 'attachments']
+           'url', 'attendees', 'email', 'attachments', 'start', 'end']

diff -U0 -r /tmp/gcalcli_2021-06-21/gcal.py ./gcal.py
--- /tmp/gcalcli_2021-06-21/gcal.py	2021-06-20 17:05:38.000000000 -0700
+++ ./gcal.py	2021-06-21 15:05:16.000000000 -0700
@@ -10,0 +11 @@
+from pytz import timezone
@@ -758,0 +760,16 @@
+        if self.details.get('start'):
+            if event['start'].get('timeZone'):
+                start_dt_full = parse(event['start']['dateTime']).astimezone(timezone(event['start']['timeZone']))
+            else:
+                start_dt_full = parse(event['start']['dateTime'])
+            xstr = '%s  Start: %s (%s; UTC%s)\n' % (details_indent, start_dt_full.strftime("%Y-%m-%d %H:%M"), start_dt_full.tzname(), start_dt_full.strftime("%z"))
+            self.printer.msg(xstr, 'default')
+
+        if self.details.get('end'):
+            if event['start'].get('timeZone'):
+                end_dt_full = parse(event['end']['dateTime']).astimezone(timezone(event['end']['timeZone']))
+            else:
+                end_dt_full = parse(event['end']['dateTime'])
+            xstr = '%s  End: %s (%s; UTC%s)\n' % (details_indent, end_dt_full.strftime("%Y-%m-%d %H:%M"), end_dt_full.tzname(), end_dt_full.strftime("%z"))
+            self.printer.msg(xstr, 'default')
+
@@ -760 +777,9 @@
-            diff_date_time = (event['e'] - event['s'])
+            if event['start'].get('timeZone'):
+                start_dt_full = parse(event['start']['dateTime']).astimezone(timezone(event['start']['timeZone']))
+            else:
+                start_dt_full = parse(event['start']['dateTime'])
+            if event['start'].get('timeZone'):
+                end_dt_full = parse(event['end']['dateTime']).astimezone(timezone(event['end']['timeZone']))
+            else:
+                end_dt_full = parse(event['end']['dateTime'])
+            diff_date_time = (end_dt_full - start_dt_full)

from gcalcli.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.