|
@@ -606,7 +606,7 @@ def timestamp(s):
|
|
|
try:
|
|
|
# is it pointing to a file / directory?
|
|
|
ts = safe_s(os.stat(s).st_mtime)
|
|
|
- return datetime.utcfromtimestamp(ts)
|
|
|
+ return datetime.fromtimestamp(ts, tz=timezone.utc)
|
|
|
except OSError:
|
|
|
# didn't work, try parsing as timestamp. UTC, no TZ, no microsecs support.
|
|
|
for format in ('%Y-%m-%dT%H:%M:%SZ', '%Y-%m-%dT%H:%M:%S+00:00',
|
|
@@ -615,7 +615,7 @@ def timestamp(s):
|
|
|
'%Y-%m-%d', '%Y-%j',
|
|
|
):
|
|
|
try:
|
|
|
- return datetime.strptime(s, format)
|
|
|
+ return datetime.strptime(s, format).replace(tzinfo=timezone.utc)
|
|
|
except ValueError:
|
|
|
continue
|
|
|
raise ValueError
|
|
@@ -718,7 +718,7 @@ def format_line(format, data):
|
|
|
raise PlaceholderError(format, data, e.__class__.__name__, str(e))
|
|
|
|
|
|
|
|
|
-def replace_placeholders(text):
|
|
|
+def replace_placeholders(text, overrides={}):
|
|
|
"""Replace placeholders in text with their values."""
|
|
|
from .platform import fqdn, hostname
|
|
|
current_time = datetime.now(timezone.utc)
|
|
@@ -735,6 +735,7 @@ def replace_placeholders(text):
|
|
|
'borgmajor': '%d' % borg_version_tuple[:1],
|
|
|
'borgminor': '%d.%d' % borg_version_tuple[:2],
|
|
|
'borgpatch': '%d.%d.%d' % borg_version_tuple[:3],
|
|
|
+ **overrides,
|
|
|
}
|
|
|
return format_line(text, data)
|
|
|
|
|
@@ -1103,13 +1104,13 @@ class Location:
|
|
|
| # or
|
|
|
""" + optional_archive_re, re.VERBOSE) # archive name (optional, may be empty)
|
|
|
|
|
|
- def __init__(self, text=''):
|
|
|
- if not self.parse(text):
|
|
|
+ def __init__(self, text='', overrides={}):
|
|
|
+ if not self.parse(text, overrides):
|
|
|
raise ValueError('Invalid location format: "%s"' % self.orig)
|
|
|
|
|
|
- def parse(self, text):
|
|
|
+ def parse(self, text, overrides={}):
|
|
|
self.orig = text
|
|
|
- text = replace_placeholders(text)
|
|
|
+ text = replace_placeholders(text, overrides)
|
|
|
valid = self._parse(text)
|
|
|
if valid:
|
|
|
return True
|
|
@@ -1202,6 +1203,12 @@ class Location:
|
|
|
':{}'.format(self.port) if self.port else '',
|
|
|
path)
|
|
|
|
|
|
+ def with_timestamp(self, timestamp):
|
|
|
+ return Location(self.orig, overrides={
|
|
|
+ 'now': DatetimeWrapper(timestamp.astimezone(None)),
|
|
|
+ 'utcnow': DatetimeWrapper(timestamp),
|
|
|
+ })
|
|
|
+
|
|
|
|
|
|
def location_validator(archive=None, proto=None):
|
|
|
def validator(text):
|