PR#2424: Fix time formatting for timezone values
Merges #2424 https://pagure.io/koji/pull-request/2424 Fixes: #2423 https://pagure.io/koji/issue/2423 1.22.0 sql update leaves some builds unreachable
This commit is contained in:
commit
b104e7a141
20 changed files with 96 additions and 31 deletions
|
|
@ -5275,8 +5275,8 @@ Build Info: %(weburl)s/buildinfo?buildID=%(build_id)i\r
|
|||
if target is not None:
|
||||
dest_tag = target['dest_tag_name']
|
||||
status = koji.BUILD_STATES[build['state']].lower()
|
||||
creation_time = koji.formatTimeLong(build['creation_time'])
|
||||
completion_time = koji.formatTimeLong(build['completion_time'])
|
||||
creation_time = koji.formatTimeLong(build['creation_ts'])
|
||||
completion_time = koji.formatTimeLong(build['completion_ts'])
|
||||
task_id = build['task_id']
|
||||
|
||||
task_data = self._getTaskData(task_id)
|
||||
|
|
|
|||
|
|
@ -3225,7 +3225,7 @@ def anon_handle_buildinfo(goptions, session, args):
|
|||
print("Task: %s %s" % (task['id'], koji.taskLabel(task)))
|
||||
else:
|
||||
print("Task: none")
|
||||
print("Finished: %s" % koji.formatTimeLong(info['completion_time']))
|
||||
print("Finished: %s" % koji.formatTimeLong(info['completion_ts']))
|
||||
maven_info = session.getMavenBuild(info['id'])
|
||||
if maven_info:
|
||||
print("Maven groupId: %s" % maven_info['group_id'])
|
||||
|
|
@ -4662,7 +4662,7 @@ def _do_parseTaskParams(session, method, task_id, topdir):
|
|||
oldrepo = params[2]
|
||||
if oldrepo:
|
||||
lines.append("Old Repo ID: %i" % oldrepo['id'])
|
||||
lines.append("Old Repo Creation: %s" % koji.formatTimeLong(oldrepo['creation_time']))
|
||||
lines.append("Old Repo Creation: %s" % koji.formatTimeLong(oldrepo['create_ts']))
|
||||
if len(params) > 3:
|
||||
lines.append("External Repos: %s" %
|
||||
', '.join([ext['external_repo_name'] for ext in params[3]]))
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import xml.sax
|
|||
import xml.sax.handler
|
||||
from fnmatch import fnmatch
|
||||
|
||||
import dateutil.parser
|
||||
import requests
|
||||
import six
|
||||
import six.moves.configparser
|
||||
|
|
@ -3269,10 +3270,12 @@ class DBHandler(logging.Handler):
|
|||
|
||||
def formatTime(value):
|
||||
"""Format a timestamp so it looks nicer"""
|
||||
if not value:
|
||||
if not value and not isinstance(value, (int, float)):
|
||||
return ''
|
||||
if isinstance(value, xmlrpc_client.DateTime):
|
||||
value = datetime.datetime.strptime(value.value, "%Y%m%dT%H:%M:%S")
|
||||
elif isinstance(value, (int, float)):
|
||||
value = datetime.datetime.fromtimestamp(value)
|
||||
if isinstance(value, datetime.datetime):
|
||||
return value.strftime('%Y-%m-%d %H:%M:%S')
|
||||
else:
|
||||
|
|
@ -3288,12 +3291,22 @@ def formatTimeLong(value):
|
|||
"""Format a timestamp to a more human-reable format, i.e.:
|
||||
Sat, 07 Sep 2002 00:00:01 GMT
|
||||
"""
|
||||
if not value:
|
||||
if not value and not isinstance(value, (int, float)):
|
||||
return ''
|
||||
if isinstance(value, six.string_types):
|
||||
t = dateutil.parser.parse(value)
|
||||
elif isinstance(value, xmlrpc_client.DateTime):
|
||||
t = dateutil.parser.parse(value.value)
|
||||
elif isinstance(value, (int, float)):
|
||||
t = datetime.datetime.fromtimestamp(value)
|
||||
else:
|
||||
# Assume the string value passed in is the local time
|
||||
localtime = time.mktime(time.strptime(formatTime(value), '%Y-%m-%d %H:%M:%S'))
|
||||
return time.strftime('%a, %d %b %Y %H:%M:%S %Z', time.localtime(localtime))
|
||||
t = value
|
||||
# return date in local timezone, py 2.6 has tzone as astimezone required parameter
|
||||
# would work simply as t.astimezone() for py 2.7+
|
||||
if t.tzinfo is None:
|
||||
t = t.replace(tzinfo=dateutil.tz.gettz())
|
||||
t = t.astimezone(dateutil.tz.gettz())
|
||||
return datetime.datetime.strftime(t, '%a, %d %b %Y %H:%M:%S %Z')
|
||||
|
||||
|
||||
def buildLabel(buildInfo, showEpoch=False):
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ Tag: f23
|
|||
Status: complete
|
||||
Built by: user
|
||||
ID: 612609
|
||||
Started: Wed, 18 Feb 2015 14:50:37 EST
|
||||
Finished: Wed, 18 Feb 2015 14:57:37 EST
|
||||
Started: Wed, 18 Feb 2015 09:50:37 EST
|
||||
Finished: Wed, 18 Feb 2015 09:57:37 EST
|
||||
Changelog:
|
||||
* Wed Feb 18 2015 Happy Koji User <user@example.com> - 1:0.3.0-0.2.M1
|
||||
- Unbundle ASM
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ class MyClientSession(koji.ClientSession):
|
|||
class TestBuildNotification(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.maxDiff = None
|
||||
self.original_timezone = os.environ.get('TZ')
|
||||
os.environ['TZ'] = 'US/Eastern'
|
||||
time.tzset()
|
||||
|
|
@ -111,5 +112,5 @@ class TestBuildNotification(unittest.TestCase):
|
|||
msg_expect = fp.read()
|
||||
if six.PY2:
|
||||
msg_expect = msg_expect.decode()
|
||||
self.assertEqual(message, msg_expect)
|
||||
self.assertMultiLineEqual(message.decode(), msg_expect.decode())
|
||||
locale.resetlocale()
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ class TestParseTaskParams(utils.CliTestCase):
|
|||
self.__run_parseTask_test('prepRepo', params, expect)
|
||||
|
||||
def test_createRepo(self):
|
||||
params = [1, 'x86_64', {'id': 1, 'creation_time': '1970-1-1 0:0:0'},
|
||||
params = [1, 'x86_64', {'id': 1, 'create_ts': 0},
|
||||
[{'external_repo_name': 'fedoraproject.net'},
|
||||
{'external_repo_name': 'centos.org'}]]
|
||||
expect = ["Repo ID: %i" % params[0]]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
from __future__ import absolute_import
|
||||
import datetime
|
||||
import os
|
||||
import time
|
||||
import locale
|
||||
try:
|
||||
import unittest2 as unittest
|
||||
|
|
@ -11,6 +13,16 @@ import six.moves.xmlrpc_client as xmlrpc_client
|
|||
from koji import formatTime, formatTimeLong
|
||||
|
||||
class TestFormatTime(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self._orig_tz = os.environ.get('TZ')
|
||||
|
||||
def tearDown(self):
|
||||
if self._orig_tz:
|
||||
os.environ['TZ'] = self._orig_tz
|
||||
elif 'TZ' in os.environ:
|
||||
del os.environ['TZ']
|
||||
time.tzset()
|
||||
|
||||
def test_format_time(self):
|
||||
self.assertEqual(formatTime(None), '')
|
||||
self.assertEqual(formatTime(''), '')
|
||||
|
|
@ -33,6 +45,8 @@ class TestFormatTime(unittest.TestCase):
|
|||
def test_format_time_long(self):
|
||||
# force locale to compare 'desired' value
|
||||
locale.setlocale(locale.LC_ALL, ('en_US', 'UTF-8'))
|
||||
os.environ['TZ'] = 'GMT'
|
||||
time.tzset()
|
||||
|
||||
self.assertEqual(formatTimeLong(None), '')
|
||||
self.assertEqual(formatTimeLong(''), '')
|
||||
|
|
@ -62,4 +76,41 @@ class TestFormatTime(unittest.TestCase):
|
|||
r = r[:r.rfind(' ')]
|
||||
self.assertEqual(r, desired)
|
||||
|
||||
# str + timezone
|
||||
d3 = '2017-10-05 09:52:31+02:00'
|
||||
desired = 'Thu, 05 Oct 2017 07:52:31 GMT'
|
||||
os.environ['TZ'] = 'GMT'
|
||||
time.tzset()
|
||||
r = formatTimeLong(d3)
|
||||
self.assertEqual(r, desired)
|
||||
|
||||
# non-GMT without DST
|
||||
d3 = '2017-06-05 09:52:31+02:00'
|
||||
desired = 'Mon, 05 Jun 2017 09:52:31 CEST'
|
||||
os.environ['TZ'] = 'Europe/Prague'
|
||||
time.tzset()
|
||||
r = formatTimeLong(d3)
|
||||
self.assertEqual(r, desired)
|
||||
|
||||
# non-GMT with DST
|
||||
d3 = '2017-12-05 09:52:31+02:00'
|
||||
desired = 'Tue, 05 Dec 2017 08:52:31 CET'
|
||||
os.environ['TZ'] = 'Europe/Prague'
|
||||
time.tzset()
|
||||
r = formatTimeLong(d3)
|
||||
self.assertEqual(r, desired)
|
||||
|
||||
# timestamps, local timezone
|
||||
d4 = 0
|
||||
desired = 'Thu, 01 Jan 1970 01:00:00 CET'
|
||||
r = formatTimeLong(d4)
|
||||
self.assertEqual(r, desired)
|
||||
|
||||
# timestamps, GMT
|
||||
desired = 'Thu, 01 Jan 1970 00:00:00 GMT'
|
||||
os.environ['TZ'] = 'GMT'
|
||||
time.tzset()
|
||||
r = formatTimeLong(d4)
|
||||
self.assertEqual(r, desired)
|
||||
|
||||
locale.resetlocale()
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
<td>$build.volume_name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Started</th><td>$util.formatTimeLong($start_time)</td>
|
||||
<th>Started</th><td>$util.formatTimeLong($start_ts)</td>
|
||||
</tr>
|
||||
#if $build.state == $koji.BUILD_STATES.BUILDING
|
||||
#if $estCompletion
|
||||
|
|
@ -79,7 +79,7 @@
|
|||
#end if
|
||||
#else
|
||||
<tr>
|
||||
<th>Completed</th><td>$util.formatTimeLong($build.completion_time)</td>
|
||||
<th>Completed</th><td>$util.formatTimeLong($build.completion_ts)</td>
|
||||
</tr>
|
||||
#end if
|
||||
#if $build.cg_id
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@
|
|||
<td><a href="taginfo?tagID=$build.tag_id">$build.tag_name</a></td>
|
||||
#end if
|
||||
<td class="user-$build.owner_name"><a href="userinfo?userID=$build.owner_id">$build.owner_name</a></td>
|
||||
<td>$util.formatTime($build.completion_time)</td>
|
||||
<td>$util.formatTime($build.completion_ts)</td>
|
||||
#set $stateName = $util.stateName($build.state)
|
||||
<td class="$stateName">$util.stateImage($build.state)</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
</tr>
|
||||
#if 'mtime' in $file and $file.mtime
|
||||
<tr>
|
||||
<th>Modification time</th><td>$util.formatTimeLong($datetime.datetime.fromtimestamp($file.mtime))</td>
|
||||
<th>Modification time</th><td>$util.formatTimeLong($file.mtime)</td>
|
||||
</tr>
|
||||
#end if
|
||||
#if 'user' in $file and $file.user
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#if not $user
|
||||
<td class="user-$build.owner_name"><a href="userinfo?userID=$build.owner_id">$build.owner_name</a></td>
|
||||
#end if
|
||||
<td>$util.formatTime($build.completion_time)</td>
|
||||
<td>$util.formatTime($build.completion_ts)</td>
|
||||
<td class="$stateName">$util.stateImage($build.state)</td>
|
||||
</tr>
|
||||
#end for
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
</td>
|
||||
#end if
|
||||
<td>$task.arch</td>
|
||||
<td>$util.formatTime($task.completion_time)</td>
|
||||
<td>$util.formatTime($task.completion_ts)</td>
|
||||
<td class="task$state">$util.imageTag($state)</td>
|
||||
</tr>
|
||||
#end for
|
||||
|
|
|
|||
|
|
@ -1279,12 +1279,12 @@ def buildinfo(environ, buildID):
|
|||
if field not in values:
|
||||
values[field] = None
|
||||
|
||||
values['start_time'] = build.get('start_time') or build['creation_time']
|
||||
values['start_ts'] = build.get('start_ts') or build['creation_ts']
|
||||
# the build start time is not accurate for maven and win builds, get it from the
|
||||
# task start time instead
|
||||
if 'maven' in typeinfo or 'win' in typeinfo:
|
||||
if task:
|
||||
values['start_time'] = task['start_time']
|
||||
values['start_ts'] = task['start_ts']
|
||||
if build['state'] == koji.BUILD_STATES['BUILDING']:
|
||||
avgDuration = server.getAverageBuildDuration(build['package_id'])
|
||||
if avgDuration is not None:
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
<tr class="$util.rowToggle($self)">
|
||||
<td><a href="buildinfo?buildID=$build.build_id">$build.nvr</a></td>
|
||||
<td class="user-$build.owner_name"><a href="userinfo?userID=$build.owner_id">$build.owner_name</a></td>
|
||||
<td>$util.formatTime($build.completion_time)</td>
|
||||
<td>$util.formatTime($build.completion_ts)</td>
|
||||
#set $stateName = $util.stateName($build.state)
|
||||
<td class="$stateName">$util.stateImage($build.state)</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
<title>$koji.BUILD_STATES[$build.state].lower(): $koji.buildLabel($build)#if $build.task then ', target: ' + $build.task.request[1] else ''#</title>
|
||||
<link>$weburl/buildinfo?buildID=$build.build_id</link>
|
||||
#if $build.completion_time
|
||||
<pubDate>$util.formatTimeRSS($build.completion_time)</pubDate>
|
||||
<pubDate>$util.formatTimeRSS($build.completion_ts)</pubDate>
|
||||
#end if
|
||||
#if $build.state == $koji.BUILD_STATES['COMPLETE'] and $build.changelog
|
||||
<description><pre>$util.escapeHTML($koji.util.formatChangelog($build.changelog))</pre></description>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<tr><th>Tag</th><td><a href="taginfo?tagID=$repo.tag_id">$repo.tag_name</a></td></tr>
|
||||
#set $state = $util.repoState($repo.state)
|
||||
<tr><th>State</th><td class="repo$state">$state</td></tr>
|
||||
<tr><th>Event</th><td>$repo.create_event ($util.formatTimeLong($repo.creation_time))</td></tr>
|
||||
<tr><th>Event</th><td>$repo.create_event ($util.formatTimeLong($repo.create_ts))</td></tr>
|
||||
#if $repo.state != koji.REPO_STATES['DELETED']
|
||||
<tr><th>URL</th><td><a href="$url">repodata</a></td></tr>
|
||||
<tr><th>Repo json</th><td><a href="$repo_json">repo.json</a></td></tr>
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@
|
|||
<th>Repo created</th>
|
||||
<td>
|
||||
#if $repo
|
||||
<a href="repoinfo?repoID=$repo.id">$util.formatTimeRSS($repo.creation_time)</a>
|
||||
<a href="repoinfo?repoID=$repo.id">$util.formatTimeRSS($repo.create_ts)</a>
|
||||
#end if
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -77,11 +77,11 @@
|
|||
#end for
|
||||
#end if
|
||||
<tr>
|
||||
<th>Created</th><td>$util.formatTimeLong($task.create_time)</td>
|
||||
<th>Created</th><td>$util.formatTimeLong($task.create_ts)</td>
|
||||
</tr>
|
||||
#if $task.start_time
|
||||
<tr>
|
||||
<th>Started</th><td>$util.formatTimeLong($task.start_time)</td>
|
||||
<th>Started</th><td>$util.formatTimeLong($task.start_ts)</td>
|
||||
#end if
|
||||
#set $end_ts = None
|
||||
#if $task.state == $koji.TASK_STATES.OPEN
|
||||
|
|
@ -93,7 +93,7 @@
|
|||
#end if
|
||||
#elif $task.completion_time
|
||||
<tr>
|
||||
<th>Completed</th><td>$util.formatTimeLong($task.completion_time)</td>
|
||||
<th>Completed</th><td>$util.formatTimeLong($task.completion_ts)</td>
|
||||
</tr>
|
||||
#set $end_ts = $task.completion_ts
|
||||
#end if
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ $printOpts($params[3])
|
|||
#set $oldrepo = $params[2]
|
||||
#if $oldrepo
|
||||
<strong>Old Repo ID:</strong> <a href="repoinfo?repoID=$oldrepo.id">$oldrepo.id</a><br/>
|
||||
<strong>Old Repo Creation:</strong> $koji.formatTimeLong($oldrepo.creation_time)<br/>
|
||||
<strong>Old Repo Creation:</strong> $koji.formatTimeLong($oldrepo.create_ts)<br/>
|
||||
#end if
|
||||
#if $len($params) > 4 and $params[4]
|
||||
<strong>External Repos:</strong> $printValue(None, [ext['external_repo_name'] for ext in $params[3]])<br/>
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ All
|
|||
#end if
|
||||
</td>
|
||||
<td>$task.arch</td>
|
||||
<td>$util.formatTime($task.completion_time)</td>
|
||||
<td>$util.formatTime($task.completion_ts)</td>
|
||||
<td class="task$state">$util.imageTag($taskState)</td>
|
||||
</tr>
|
||||
#end for
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@
|
|||
<tr class="$util.rowToggle($self)">
|
||||
#set $stateName = $util.stateName($build.state)
|
||||
<td><a href="buildinfo?buildID=$build.build_id">$build.nvr</a></td>
|
||||
<td>$util.formatTime($build.completion_time)</td>
|
||||
<td>$util.formatTime($build.completion_ts)</td>
|
||||
<td class="$stateName">$util.stateImage($build.state)</td>
|
||||
</tr>
|
||||
#end for
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue