Commit 3a96758e authored by Stavros Sachtouris's avatar Stavros Sachtouris

Add timezone support in DateArgument

parent 91cd8874
...@@ -9,6 +9,7 @@ Bug Fixes: ...@@ -9,6 +9,7 @@ Bug Fixes:
Support: Support:
- Adjust project commands to project_API changes [#5025] - Adjust project commands to project_API changes [#5025]
- Add dateutils to dependencies
Features: Features:
- Name and Type filters in endpoint list - Name and Type filters in endpoint list
......
...@@ -37,6 +37,8 @@ from kamaki.cli.errors import ( ...@@ -37,6 +37,8 @@ from kamaki.cli.errors import (
from kamaki.cli.utils import split_input, to_bytes from kamaki.cli.utils import split_input, to_bytes
from datetime import datetime as dtm from datetime import datetime as dtm
import dateutil.tz
import dateutil.parser
from time import mktime from time import mktime
from sys import stderr from sys import stderr
...@@ -357,9 +359,10 @@ class UserAccountArgument(ValueArgument): ...@@ -357,9 +359,10 @@ class UserAccountArgument(ValueArgument):
class DateArgument(ValueArgument): class DateArgument(ValueArgument):
DATE_FORMAT = '%a %b %d %H:%M:%S %Y' DATE_FORMATS = ['%a %b %d %H:%M:%S %Y', '%d-%m-%Y', '%H:%M:%S %d-%m-%Y']
INPUT_FORMATS = [
INPUT_FORMATS = [DATE_FORMAT, '%d-%m-%Y', '%H:%M:%S %d-%m-%Y'] 'YYYY-mm-dd', '"HH:MM:SS YYYY-mm-dd"', 'YYYY-mm-ddTHH:MM:SS+TMZ',
'"Day Mon dd HH:MM:SS YYYY"']
@property @property
def timestamp(self): def timestamp(self):
...@@ -369,7 +372,7 @@ class DateArgument(ValueArgument): ...@@ -369,7 +372,7 @@ class DateArgument(ValueArgument):
@property @property
def formated(self): def formated(self):
v = getattr(self, '_value', self.default) v = getattr(self, '_value', self.default)
return v.strftime(self.DATE_FORMAT) if v else None return v.strftime(self.DATE_FORMATS[0]) if v else None
@property @property
def value(self): def value(self):
...@@ -377,23 +380,32 @@ class DateArgument(ValueArgument): ...@@ -377,23 +380,32 @@ class DateArgument(ValueArgument):
@property @property
def isoformat(self): def isoformat(self):
v = getattr(self, '_value', self.default) d = getattr(self, '_value', self.default)
return v.isoformat() if v else None if not d:
return None
if not d.tzinfo:
d = d.replace(tzinfo=dateutil.tz.tzlocal())
return d.isoformat()
@value.setter @value.setter
def value(self, newvalue): def value(self, newvalue):
self._value = self.format_date(newvalue) if newvalue else self.default if newvalue:
try:
self._value = dateutil.parser.parse(newvalue)
except Exception:
raise CLIInvalidArgument(
'Invalid value "%s" for date argument %s' % (
newvalue, self.lvalue),
details=['Suggested formats:'] + self.INPUT_FORMATS)
def format_date(self, datestr): def format_date(self, datestr):
for format in self.INPUT_FORMATS: for fmt in self.DATE_FORMATS:
try: try:
t = dtm.strptime(datestr, format) return dtm.strptime(datestr, fmt)
except ValueError: except ValueError as ve:
continue continue
return t # .strftime(self.DATE_FORMAT) raise raiseCLIError(ve, 'Failed to format date', details=[
raiseCLIError(None, 'Date Argument Error', details=[ '%s could not be formated for HTTP headers' % datestr])
'%s not a valid date' % datestr,
'Correct formats:\n\t%s' % self.INPUT_FORMATS])
class VersionArgument(FlagArgument): class VersionArgument(FlagArgument):
......
...@@ -838,8 +838,8 @@ class project_modify(_init_synnefo_astakosclient, _optional_json): ...@@ -838,8 +838,8 @@ class project_modify(_init_synnefo_astakosclient, _optional_json):
('homepage', self['homepage_url']), ('homepage', self['homepage_url']),
('description', self['description']), ('description', self['description']),
('max_members', self['max_members']), ('max_members', self['max_members']),
('start_date', self['start_date']), ('start_date', self.arguments['start_date'].isoformat),
('end_date', self['end_date']), ('end_date', self.arguments['end_date'].isoformat),
('join_policy', self['join_policy']), ('join_policy', self['join_policy']),
('leave_policy', self['leave_policy']), ('leave_policy', self['leave_policy']),
('resources', self['resource_capacities'])): ('resources', self['resource_capacities'])):
...@@ -960,7 +960,7 @@ class membership_list(_init_synnefo_astakosclient, _optional_json): ...@@ -960,7 +960,7 @@ class membership_list(_init_synnefo_astakosclient, _optional_json):
"""List all memberships""" """List all memberships"""
arguments = dict( arguments = dict(
project=IntArgument('Filter by project id', '--project-id') project=ValueArgument('Filter by project id', '--project-id')
) )
@errors.generic.all @errors.generic.all
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
# interpreted as representing official policies, either expressed # interpreted as representing official policies, either expressed
# or implied, of GRNET S.A. # or implied, of GRNET S.A.
from sys import stdout, stdin, stderr from sys import stdout, stderr
from re import compile as regex_compile from re import compile as regex_compile
from os import walk, path from os import walk, path
from json import dumps from json import dumps
......
...@@ -41,7 +41,7 @@ import kamaki ...@@ -41,7 +41,7 @@ import kamaki
optional = ['ansicolors', 'mock>=1.0.1'] optional = ['ansicolors', 'mock>=1.0.1']
requires = ['objpool>=0.2', 'progress>=1.1', 'astakosclient>=0.14.10'] requires = ['objpool>=0.2', 'progress>=1.1', 'astakosclient>=0.14.10', 'dateutils']
if version_info < (2, 7): if version_info < (2, 7):
requires.append('argparse') requires.append('argparse')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment