1

So i have been trying to add a time format to my REST calls in python, but there seems to always be some type of issue, first of all here is the time format requirement, and it has to be exact, or it wont work unfortunately.

Use the following ISO-8601 compliant date/time format in request parameters.

yyyy-MM-dd'T'HH:mm:ss.SSSXXX

For example, May 26 2014 at 21:49:46 PM could have a format like one of the following:

l In PDT: 2014-05-26T21:49:46.000-07:00

l In UTC: 2014-05-26T21:49:46.000Z

Code Description

  • yyyy Four digit year
  • MM Two-digit month (01=January, etc.)
  • dd Two-digit day of month (01 through 31)
  • T Separator for date/time
  • HH Two digits of hour (00 through 23) (am/pm NOT allowed)
  • mm Two digits of minute (00 through 59)
  • ss Two digits of second (00 through 59)
  • SSS Three digit milliseconds of the second
  • XXX ISO 8601 time zone (Z or +hh:mm or -hh:mm)

So, what i have tried before is:

def format_time(self, isnow):
    currentdt = datetime.datetime.utcnow()
    if not isnow:
        currentdt += datetime.timedelta(0,3)
    (dt, micro) = currentdt.strftime('%Y-%m-%dT%H:%M:%S.%f').split('.')
    dt = "%s.%03dZ" % (dt, int(micro) / 1000)
    return dt

Now, this might return it in the kinda right format, but there is still the problem with timezones.

The end result i am trying to accomplish, is when i execute this, it finds the current time, (Amsterdam timezone/GMT/UTC+1), and creates it in this format. And the else statement, to get the same time, but append X seconds.

Would anyone be so kind to help me out here?

Scott Mermelstein
  • 15,174
  • 4
  • 48
  • 76
Marius
  • 186
  • 2
  • 13
  • Tangent that won't solve your problem, but will make your code simpler to maintain (and your problem simpler to answer): `currentdt = datetime.datetime.utcnow()` `if not isnow: currentdt += datetime.timedelta(0,3)` `(dt, etc...` In other words, the only thing in the if block should just be adding the timedelta. That separates your getting the time from you formatting the time. I can rewrite it for you in your question, if you want. (Usually, editors don't change code blocks, since then they're changing the question.) I'd also edit out the unnecessary vulgarity while I'm there... – Scott Mermelstein Nov 14 '16 at 16:50
  • @ScottMermelstein Changed out the function name, sorry about that. If i understood your other point, do you want me to change out what i currently tried, to a more simplified format, and then see if someone can present me an answer? – Marius Nov 14 '16 at 16:53
  • It's a recommendation, not a requirement. By using the more simplified format, you'd only need to fix one line of code. As it is, of the 10 lines you posted, 3 of them are a copy of the other 3. And since the issue is in those 3 lines, it would be cleaner to address that way. I'll make the change, because it's much easier to put in the question than in a comment; if you don't like it, click on "edited X mins ago", and roll it back. – Scott Mermelstein Nov 14 '16 at 16:57
  • @ScottMermelstein Ah that is fair, i do not mind this at all :) Thanks for the help so far! – Marius Nov 14 '16 at 17:00

1 Answers1

1

Ok, so you got the microseconds formatted as milliseconds, well done there.

Now your challenge is to handle the timezone offset; it can't only be Z.

And to make things more difficult, strftime's %z format gives + (or -) HHMM, instead of HH:MM.

So you'll need to deal with that. Here's one way to do it:

Python 3:

def format_time(self, isnow):
    currentdt = datetime.datetime.now(datetime.timezone.utc)
    if not isnow:
        currentdt += datetime.timedelta(0,3)
    (dt, micro) = currentdt.strftime('%Y-%m-%dT%H:%M:%S.%f').split('.')
    tz_offset = currentdt.astimezone().strftime('%z')
    tz_offset = "Z" if tz_offset == "" else tz_offset[:3] + ":" + tz_offset[3:]

    dt = "%s.%03d%s" % (dt, int(micro) / 1000, tz_offset)
    return dt

Python 2:

import pytz
from dateutil.tz import *

def format_time(self, isnow):
    currentdt = datetime.datetime.now(pytz.utc)
    if not isnow:
        currentdt += datetime.timedelta(0,3)
    (dt, micro) = currentdt.strftime('%Y-%m-%dT%H:%M:%S.%f').split('.')
    tz_offset = currentdt.astimezone(tzlocal()).strftime('%z')
    tz_offset = "Z" if tz_offset == "" else tz_offset[:3] + ":" + tz_offset[3:]

    dt = "%s.%03d%s" % (dt, int(micro) / 1000, tz_offset)
    return dt

Response to comment: I needed to make a few changes. It's remarkably non-trivial to find the current timezone. The easiest way I could find was from https://stackoverflow.com/a/25887393/1404311 and I've integrated those concepts into the code that is now above.

Basically, instead of utcnow(), you should use now(datetime.timezone.utc). The former gives a naive datetime, while the latter gives a datetime set to UTC, but aware that it is. Then use astimezone() to make it aware of your local timezone, then use strftime('%z') to get the time offzone from there. THEN go through the string manipulation.

Community
  • 1
  • 1
Scott Mermelstein
  • 15,174
  • 4
  • 48
  • 76
  • Hmm, okay, this seems doable, but first, what is the else here supposed to mean? `tz = "Z" if tz == "" else`. This would give me an error.. Also, how would this then be able to be converted to the correct timezone? Is the utcnow time always the same, and if i add the extra "00:00", at the end of the time format, it will be converted? – Marius Nov 14 '16 at 17:28
  • Ack. Sorry about that, I'm not sure why I didn't finish editing my code. Fixed... – Scott Mermelstein Nov 14 '16 at 17:45
  • Ok, my edits should give you much more timezone awareness now. :-) – Scott Mermelstein Nov 14 '16 at 18:11
  • I am guessing this is one more reason i would have to jump to python3 :p Seeing as that is only for python3. I guess i could still use pytz and get the same thing? – Marius Nov 14 '16 at 18:39
  • Since i can't edit my comment anymore, so il add a new comment. Maybe also arrow would be a good choice? If i already need to import a new library (like pytz): http://crsmithdev.com/arrow/ – Marius Nov 14 '16 at 18:47
  • I hadn't realized my solution was only python 3. Sorry. :-( If you want to find the system's local time zone using Python 2, try my newest edit. :-) – Scott Mermelstein Nov 14 '16 at 19:00
  • And that returns exactly what i needed, thank you so much for your time! :) – Marius Nov 14 '16 at 19:30