From 4c680115969ea6f610e60f600c7b97569d887731 Mon Sep 17 00:00:00 2001
From: Jana Cupova <root@localhost>
Date: Oct 25 2021 13:17:28 +0000
Subject: Add option for UTC time in list-history


Fixes: https://pagure.io/koji/issue/1136

---

diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py
index 3f8f84c..a187f81 100644
--- a/cli/koji_cli/commands.py
+++ b/cli/koji_cli/commands.py
@@ -13,6 +13,8 @@ import sys
 import textwrap
 import time
 import traceback
+from datetime import datetime
+from dateutil.tz import tzutc
 from collections import OrderedDict, defaultdict
 from optparse import SUPPRESS_HELP, OptionParser
 
@@ -4615,7 +4617,11 @@ def _print_histline(entry, **kwargs):
             fmt = "%s entry created" % table
         else:
             fmt = "%s entry revoked" % table
-    time_str = time.asctime(time.localtime(ts))
+    if options.utc:
+        time_str = time.asctime(datetime.fromtimestamp(ts, tzutc()).timetuple())
+    else:
+        time_str = time.asctime(time.localtime(ts))
+
     parts = [time_str, fmt % x]
     if options.events or options.verbose:
         parts.insert(1, "(eid %i)" % event_id)
@@ -4733,6 +4739,8 @@ def anon_handle_list_history(goptions, session, args):
     parser.add_option("-e", "--events", action="store_true", help="Show event ids")
     parser.add_option("--all", action="store_true",
                       help="Allows listing the entire global history")
+    parser.add_option("--utc", action="store_true",
+                      help="Shows time in UTC timezone")
     (options, args) = parser.parse_args(args)
     if len(args) != 0:
         parser.error("This command takes no arguments")
@@ -4759,6 +4767,8 @@ def anon_handle_list_history(goptions, session, args):
         channelinfo = session.getChannel(options.channel)
         if not channelinfo:
             error("No such channel: %s" % options.channel)
+    if options.utc:
+        kwargs['utc'] = options.utc
     tables = None
     if options.show:
         tables = []
diff --git a/tests/test_cli/test_list_history.py b/tests/test_cli/test_list_history.py
index 15539be..bc192d4 100644
--- a/tests/test_cli/test_list_history.py
+++ b/tests/test_cli/test_list_history.py
@@ -2,6 +2,8 @@ from __future__ import absolute_import
 
 import time
 from datetime import datetime
+from dateutil.tz import tzutc
+
 import unittest
 
 from six.moves import StringIO
@@ -17,23 +19,30 @@ class TestListHistory(utils.CliTestCase):
         self.options = mock.MagicMock()
         self.options.debug = False
         self.session = mock.MagicMock()
+        self.maxDiff = None
 
     @staticmethod
-    def get_expected_date_active_action(item, act='add'):
+    def get_expected_date_active_action(item, act='add', utc=False):
         if act == 'add':
-            dt = datetime.fromtimestamp(item['create_ts'])
+            if utc:
+                dt = datetime.fromtimestamp(item['create_ts'], tzutc())
+            else:
+                dt = datetime.fromtimestamp(item['create_ts'])
             if item['active']:
                 active = ' [still active]'
             else:
                 active = ''
         else:
-            dt = datetime.fromtimestamp(item['revoke_ts'])
+            if utc:
+                dt = datetime.fromtimestamp(item['create_ts'], tzutc())
+            else:
+                dt = datetime.fromtimestamp(item['revoke_ts'])
             active = ''
 
         expected_date = time.asctime(dt.timetuple())
         return expected_date, active
 
-    def get_expected_channel(self, item):
+    def get_expected_channel(self, item, utc=False):
         if item['active']:
             list_active = ['add']
         else:
@@ -41,7 +50,7 @@ class TestListHistory(utils.CliTestCase):
         expected = ''
         for act in list_active:
             expected_date, active = self.get_expected_date_active_action(
-                item, act)
+                item, act, utc)
             if act == 'add':
                 action = 'added to'
             else:
@@ -221,6 +230,36 @@ class TestListHistory(utils.CliTestCase):
     @mock.patch('sys.stderr', new_callable=StringIO)
     @mock.patch('sys.stdout', new_callable=StringIO)
     @mock.patch('koji_cli.commands.ensure_connection')
+    def test_list_history_channel_utc(self, ensure_connection_mock, stdout, stderr):
+        # test case when channel is still active
+        channel_name = 'default'
+
+        # when channel name is created
+        dict_history = {
+            'host_channels': [
+                {'active': True,
+                 'channel_id': 1,
+                 'channels.name': 'default',
+                 'create_event': 3,
+                 'create_ts': 1612355089.887727,
+                 'creator_id': 1,
+                 'creator_name': 'kojiadmin',
+                 'host.name': 'kojibuilder',
+                 'host_id': 1,
+                 'revoke_event': None,
+                 'revoke_ts': None,
+                 'revoker_id': None,
+                 'revoker_name': None}]
+        }
+        self.session.queryHistory.return_value = dict_history
+        expected = self.get_expected_channel(dict_history['host_channels'][0], utc=True)
+        anon_handle_list_history(self.options, self.session,
+                                 ['--channel', channel_name])
+        self.assert_console_message(stdout, expected)
+
+    @mock.patch('sys.stderr', new_callable=StringIO)
+    @mock.patch('sys.stdout', new_callable=StringIO)
+    @mock.patch('koji_cli.commands.ensure_connection')
     def test_list_history_channel(self, ensure_connection_mock, stdout, stderr):
         # test case when channel is still active
         channel_name = 'default'
@@ -1145,6 +1184,7 @@ Options:
   -v, --verbose         Show more detail
   -e, --events          Show event ids
   --all                 Allows listing the entire global history
+  --utc                 Shows time in UTC timezone
 """ % self.progname)
 
 

