apel/common/datetime_utils.py
'''
Copyright (C) 2012 STFC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@author Konrad Jopek, Will Rogers
'''
import iso8601
import datetime
import re
def valid_from(date, days=1):
'''
Method for BlahParser
Returns calculated value for ValidFrom field.
By default it returns Timestamp - 1 day
'''
delta = datetime.timedelta(days=days)
return date-delta
def valid_until(date, days=28):
'''
Method for BlahParser
Returns calculated value for ValidUntil field.
By default it returns Timestamp + 28 days
'''
delta = datetime.timedelta(days=days)
return date + delta
def parse_timestamp(datetime_string):
'''
Parse timestamp encoded as a string in various forms. Return
a TZ-unaware datetime object, which is in UTC.
If timezone information is not present in the string, it
assumes that the timezone is UTC.
'''
dt = iso8601.parse_date(datetime_string)
utcdt = dt.astimezone(iso8601.iso8601.UTC)
# internal representation of datetimes is UTC without timezones
return utcdt.replace(tzinfo=None)
def parse_time(timestring):
"""Return integer seconds from times of form d-h:m:s, h:m:s or m:s.s."""
if '-' in timestring:
days, sub_days = timestring.split('-')
else:
days, sub_days = 0, timestring
if '.' in sub_days:
hours = 0
minutes, decimal_s = sub_days.split(':')
seconds = int(round(float(decimal_s)))
else:
hours, minutes, seconds = sub_days.split(':')
return 86400*int(days) + 3600*int(hours) + 60*int(minutes) + int(seconds)
def iso2seconds(isoduration):
'''
Parses time interval encoded as ISO string. Returns time in seconds.
'''
pattern = "(^P)" # P required at the beginning
pattern += "([0-9]+Y)?" # years
pattern += "([0-9]+M)?" # months
pattern += "([0-9]+W)?" # weeks
pattern += "([0-9]+D)?" # days
pattern += "(T)?" # T indicates time values are starting
pattern += "([0-9]+H)?" # hours
pattern += "([0-9]+M)?" # minutes
pattern += "([0-9]+[\.,]?[0-9]*S)?" # seconds
pattern += "$" # end of string
cp = re.compile(pattern)
match = cp.match(isoduration)
values = match.groups()
intvals = []
for item in values:
try:
if ',' in item:
# ',' can be used as a decimal separator in ISO 8601
item = item.replace(',', '.')
# remove letter from end then get an int
if '.' in item:
# If item is a decimal round to integer
intvals.append(int(round(float(item[:-1]))))
else:
# Otherwise keep as an integer for accuracy
intvals.append(int(item[:-1]))
except (ValueError, TypeError):
intvals.append(0)
# ignore group 0 ("P") and group 5 ("T")
seconds = (intvals[1] * 31536000 +
intvals[2] * 2628000 +
intvals[3] * 604800 +
intvals[4] * 86400 +
intvals[6] * 3600 +
intvals[7] * 60 +
intvals[8])
return seconds