always use microseconds for ISO 8601 output

This commit is contained in:
Marian Beermann 2017-08-07 13:08:25 +02:00
parent 2ff29891f1
commit ab4981eff6
4 changed files with 26 additions and 21 deletions

View File

@ -209,9 +209,9 @@ Standard output
*stdout* is different and more command-dependent than logging. Commands like :ref:`borg_info`, :ref:`borg_create`
and :ref:`borg_list` implement a ``--json`` option which turns their regular output into a single JSON object.
Dates are formatted according to ISO-8601 in local time. Neither an explicit time zone nor microseconds
are specified *at this time* (subject to change). The equivalent strftime format string is '%Y-%m-%dT%H:%M:%S',
e.g. 2017-08-07T12:27:20.
Dates are formatted according to ISO 8601 in local time. No explicit time zone is specified *at this time*
(subject to change). The equivalent strftime format string is '%Y-%m-%dT%H:%M:%S.%f',
e.g. ``2017-08-07T12:27:20.123456``.
The root object at least contains a *repository* key with an object containing:
@ -268,7 +268,7 @@ Example *borg info* output::
},
"repository": {
"id": "0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
"last_modified": "2017-08-07T12:27:20",
"last_modified": "2017-08-07T12:27:20.789123",
"location": "/home/user/testrepo"
},
"security_dir": "/home/user/.config/borg/security/0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
@ -329,7 +329,7 @@ Example of a simple archive listing (``borg list --last 1 --json``)::
{
"id": "80cd07219ad725b3c5f665c1dcf119435c4dee1647a560ecac30f8d40221a46a",
"name": "host-system-backup-2017-02-27",
"start": "2017-08-07T12:27:20"
"start": "2017-08-07T12:27:20.789123"
}
],
"encryption": {
@ -337,7 +337,7 @@ Example of a simple archive listing (``borg list --last 1 --json``)::
},
"repository": {
"id": "0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
"last_modified": "2017-08-07T12:27:20",
"last_modified": "2017-08-07T12:27:20.789123",
"location": "/home/user/repository"
}
}
@ -355,14 +355,14 @@ The same archive with more information (``borg info --last 1 --json``)::
],
"comment": "",
"duration": 5.641542,
"end": "2017-02-27T12:27:20",
"end": "2017-02-27T12:27:20.789123",
"hostname": "host",
"id": "80cd07219ad725b3c5f665c1dcf119435c4dee1647a560ecac30f8d40221a46a",
"limits": {
"max_archive_size": 0.0001330855110409714
},
"name": "host-system-backup-2017-02-27",
"start": "2017-02-27T12:27:20",
"start": "2017-02-27T12:27:20.789123",
"stats": {
"compressed_size": 1880961894,
"deduplicated_size": 2791,
@ -388,7 +388,7 @@ The same archive with more information (``borg info --last 1 --json``)::
},
"repository": {
"id": "0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
"last_modified": "2017-08-07T12:27:20",
"last_modified": "2017-08-07T12:27:20.789123",
"location": "/home/user/repository"
}
}
@ -406,8 +406,8 @@ Refer to the *borg list* documentation for the available keys and their meaning.
Example (excerpt) of ``borg list --json-lines``::
{"type": "d", "mode": "drwxr-xr-x", "user": "user", "group": "user", "uid": 1000, "gid": 1000, "path": "linux", "healthy": true, "source": "", "linktarget": "", "flags": null, "isomtime": "2017-02-27T12:27:20", "size": 0}
{"type": "d", "mode": "drwxr-xr-x", "user": "user", "group": "user", "uid": 1000, "gid": 1000, "path": "linux/baz", "healthy": true, "source": "", "linktarget": "", "flags": null, "isomtime": "2017-02-27T12:27:20", "size": 0}
{"type": "d", "mode": "drwxr-xr-x", "user": "user", "group": "user", "uid": 1000, "gid": 1000, "path": "linux", "healthy": true, "source": "", "linktarget": "", "flags": null, "mtime": "2017-02-27T12:27:20.023407", "size": 0}
{"type": "d", "mode": "drwxr-xr-x", "user": "user", "group": "user", "uid": 1000, "gid": 1000, "path": "linux/baz", "healthy": true, "source": "", "linktarget": "", "flags": null, "mtime": "2017-02-27T12:27:20.585407", "size": 0}
.. _msgid:

View File

@ -764,7 +764,7 @@ class ItemFormatter(BaseFormatter):
return OutputTimestamp(safe_timestamp(item.get(key) or item.mtime))
def format_iso_time(self, key, item):
return self.format_time(key, item).to_json()
return self.format_time(key, item).isoformat()
def file_status(mode):

View File

@ -86,16 +86,19 @@ def safe_timestamp(item_timestamp_ns):
return datetime.fromtimestamp(t_ns / 1e9)
def format_time(t):
"""use ISO-8601-like date and time format (human readable, with wkday and blank date/time separator)
def format_time(ts: datetime):
"""
return t.strftime('%a, %Y-%m-%d %H:%M:%S')
Convert *ts* to a human-friendly format with textual weekday.
"""
return ts.strftime('%a, %Y-%m-%d %H:%M:%S')
def isoformat_time(t):
"""use ISO-8601 date and time format (machine readable, no wkday, no microseconds either)
def isoformat_time(ts: datetime):
"""
return t.strftime('%Y-%m-%dT%H:%M:%S') # note: first make all datetime objects tz aware before adding %z here.
Format *ts* according to ISO 8601.
"""
# note: first make all datetime objects tz aware before adding %z here.
return ts.strftime('%Y-%m-%dT%H:%M:%S.%f')
def format_timedelta(td):
@ -127,5 +130,7 @@ class OutputTimestamp:
def __str__(self):
return '{}'.format(self)
def to_json(self):
def isoformat(self):
return isoformat_time(self.ts)
to_json = isoformat

View File

@ -61,7 +61,7 @@ from . import key
src_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
ISO_FORMAT = '%Y-%m-%dT%H:%M:%S'
ISO_FORMAT = '%Y-%m-%dT%H:%M:%S.%f'
def exec_cmd(*args, archiver=None, fork=False, exe=None, input=b'', binary_output=False, **kw):
@ -1864,7 +1864,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
file1 = items[1]
assert file1['path'] == 'input/file1'
assert file1['size'] == 81920
assert datetime.strptime(file1['isomtime'], ISO_FORMAT) # must not raise
assert datetime.strptime(file1['mtime'], ISO_FORMAT) # must not raise
list_archive = self.cmd('list', '--json-lines', '--format={sha256}', self.repository_location + '::test')
items = [json.loads(s) for s in list_archive.splitlines()]