Repository: yast/yast-journal
Pull request #53: Fixed Regexp for Changed journalctl Output Format
Author: login: shundhammer
Created: 2025-04-27T11:59:13Z | Merged: 2025-04-29T10:37:35Z

## Bugzilla

https://bugzilla.suse.com/show_bug.cgi?id=1241904


## Problem

`yast2 journal` crashes when clicking on the "Change Filter..." button with an internal error:

```
Caller: /usr/share/YaST2/lib/y2journal/query.rb:112:in 'block in Y2Journal::Query.boots'

Details: Unexpected output for journalctl --list-boots: 
-40 472f452941c64cef8b17d9f09d0227c0 Thu 2025-03-27 21:40:38 CET Thu 2025-03-27 20:42:44 CET
```

## Cause

The output format of `journalctl --list-boots` changed subtly: It now neatly lines the timestamps up which makes it a lot better readable, even between the twice-a-year daylight savings on/off dates:

```
% journalctl --list-boots
...
...
-35 d1bedda7df99494fba2708fd3135ed3d Fri 2024-10-11 21:51:05 CEST Fri 2024-10-11 21:59:06 CEST
-34 0db89b7a57794c7ca9d280dcb1c2bd15 Fri 2024-10-11 21:59:43 CEST Fri 2024-10-18 19:04:56 CEST
-33 eb2a0791b4c74d23b1402721c6c5d887 Fri 2024-10-18 19:05:13 CEST Thu 2024-10-24 20:28:55 CEST
-32 a2ff0399994d44e2bc50aae478b56c17 Thu 2024-10-24 20:29:11 CEST Sun 2024-10-27 16:16:22 CET
-31 6a10f553edd44d6e86480c5e8b1b2e54 Sun 2024-10-27 16:16:42 CET  Tue 2024-10-29 00:55:53 CET
-30 4faaa41c488447f6bb71aea019c05a98 Tue 2024-10-29 00:56:09 CET  Wed 2024-10-30 00:53:23 CET
```

In this example, it crashes in line `-31`; there are now _two_ blanks between the first and the second timestamp.


## Fix

Allow more than one delimiter between the timestamps.

(A more robust fix would be using `--output=json`)


## Test

Manual test on my Slowroll laptop.

Without this fix, it crashes reliably if only the journal goes back before the last daylight savings -> no daylight savings change.


Diff:
diff --git a/.rubocop.yml b/.rubocop.yml
index b74ac4b..0b6d5b7 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -1,6 +1,6 @@
 # use the shared Yast defaults
 inherit_from:
-  /usr/share/YaST2/data/devtools/data/rubocop_yast_style.yml
+  /usr/share/YaST2/data/devtools/data/rubocop-1.24.1_yast_style.yml
 
 # Just raise the default threshold a little bit
 Metrics/MethodLength:
@@ -11,8 +11,8 @@ Metrics/AbcSize:
   Max: 20
 
 # We have agreed that 90 is still fine (it fits github view)
-Metrics/LineLength:
-  Max: 90
+Layout/LineLength:
+  Max: 120
 
 # journalctl output is UTF-8, so are the comments explaning it
 Style/AsciiComments:
diff --git a/Rakefile b/Rakefile
index 53db50f..c566095 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
@@ -20,6 +22,7 @@ require "yast/rake"
 
 Yast::Tasks.configuration do |conf|
   conf.skip_license_check << /test\/data\/*/
+  conf.skip_license_check << /example\/*/
   # Desktop files are just metadata
   conf.skip_license_check << /.*desktop$/
   conf.skip_license_check << /.*svg$/
diff --git a/example/log_viewer.rb b/example/log_viewer.rb
index 0aebc46..3993fb7 100644
--- a/example/log_viewer.rb
+++ b/example/log_viewer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require "yast"
 
 require "y2journal/entries_dialog"
diff --git a/package/yast2-journal.changes b/package/yast2-journal.changes
index d68cbba..33bd946 100644
--- a/package/yast2-journal.changes
+++ b/package/yast2-journal.changes
@@ -1,3 +1,11 @@
+-------------------------------------------------------------------
+Sun Apr 27 11:50:04 UTC 2025 - Stefan Hundhammer <shundhammer@suse.com>
+
+- Fixed regexp for changed 'journalctl --list-boots' output:
+  Now taking daylight savings time on/off into account
+  (bsc#1241904)
+- 5.0.2
+
 -------------------------------------------------------------------
 Thu Jan  4 13:40:35 UTC 2024 - Stefan Hundhammer <shundhammer@suse.com>
 
diff --git a/package/yast2-journal.spec b/package/yast2-journal.spec
index 236861f..fe6091f 100644
--- a/package/yast2-journal.spec
+++ b/package/yast2-journal.spec
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-journal
-Version:        5.0.1
+Version:        5.0.2
 Release:        0
 Group:          System/YaST
 License:        GPL-2.0 or GPL-3.0
diff --git a/src/clients/journal.rb b/src/clients/journal.rb
index 8932f86..4690e3b 100644
--- a/src/clients/journal.rb
+++ b/src/clients/journal.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/src/lib/y2journal.rb b/src/lib/y2journal.rb
index b59336a..0b32997 100644
--- a/src/lib/y2journal.rb
+++ b/src/lib/y2journal.rb
@@ -1,4 +1,4 @@
-# encoding: utf-8
+# frozen_string_literal: true
 
 # Copyright (c) [2018] SUSE LLC
 #
diff --git a/src/lib/y2journal/cli.rb b/src/lib/y2journal/cli.rb
index c348697..9fc7e29 100644
--- a/src/lib/y2journal/cli.rb
+++ b/src/lib/y2journal/cli.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/src/lib/y2journal/entries_dialog.rb b/src/lib/y2journal/entries_dialog.rb
index 7ce8477..3d1eb39 100644
--- a/src/lib/y2journal/entries_dialog.rb
+++ b/src/lib/y2journal/entries_dialog.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
@@ -21,7 +23,7 @@
 require "y2journal/query_presenter"
 require "y2journal/query_dialog"
 require "y2journal/journalctl_exception"
-require "yast2/popup.rb"
+require "yast2/popup"
 
 Yast.import "UI"
 Yast.import "Label"
@@ -78,6 +80,7 @@ def dialog_options
     # Event callback for the 'change filter' button.
     def filter_handler
       return unless read_query
+
       redraw_query
       execute_query
       redraw_table
diff --git a/src/lib/y2journal/entry.rb b/src/lib/y2journal/entry.rb
index 7b7be34..e3e4e73 100644
--- a/src/lib/y2journal/entry.rb
+++ b/src/lib/y2journal/entry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/src/lib/y2journal/entry_presenter.rb b/src/lib/y2journal/entry_presenter.rb
index 5976686..7309a33 100644
--- a/src/lib/y2journal/entry_presenter.rb
+++ b/src/lib/y2journal/entry_presenter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
@@ -25,9 +27,10 @@ module Y2Journal
   class EntryPresenter < SimpleDelegator
     include Yast::I18n
 
-    TIME_FORMAT = "%b %d %H:%M:%S".freeze
+    TIME_FORMAT = "%b %d %H:%M:%S"
 
     def initialize(entry)
+      super
       textdomain "journal"
       __setobj__(entry)
     end
diff --git a/src/lib/y2journal/journalctl.rb b/src/lib/y2journal/journalctl.rb
index 649fc69..eb5821f 100644
--- a/src/lib/y2journal/journalctl.rb
+++ b/src/lib/y2journal/journalctl.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
@@ -25,7 +27,7 @@ class Journalctl
     # Agent used internally
     BASH_SCR_PATH = Yast::Path.new(".target.bash_output")
     # Format understood by journalctl options
-    TIME_FORMAT = "%Y-%m-%d %H:%M:%S".freeze
+    TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
     # Ordered list of priority values supported by journalctl
     PRIORITIES = ["emerg", "alert", "crit", "err",
                   "warning", "notice", "info", "debug"].freeze
@@ -80,6 +82,7 @@ def output
 
     def options_string
       return @options_string if @option_string
+
       strings = []
       @options.each_pair do |option, value|
         if value.nil?
diff --git a/src/lib/y2journal/journalctl_exception.rb b/src/lib/y2journal/journalctl_exception.rb
index 0eeb632..6b0a3ec 100644
--- a/src/lib/y2journal/journalctl_exception.rb
+++ b/src/lib/y2journal/journalctl_exception.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2018 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/src/lib/y2journal/query.rb b/src/lib/y2journal/query.rb
index 9ddb308..6306c67 100644
--- a/src/lib/y2journal/query.rb
+++ b/src/lib/y2journal/query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
@@ -50,10 +52,9 @@ class Query
     #   repeated as many times as needed.
     # @see Y2Journal::Journalctl#initialize
     def initialize(interval: nil, filters: {})
-      unsupported = filters.keys.select { |k| !VALID_FILTERS.include?(k) }
-      if !unsupported.empty?
-        raise "Unexpected filters for the query: #{unsupported.join(", ")}"
-      end
+      unsupported = filters.keys.reject { |k| VALID_FILTERS.include?(k) }
+      raise "Unexpected filters for the query: #{unsupported.join(", ")}" unless unsupported.empty?
+
       @filters = filters
       @interval = interval
 
@@ -82,7 +83,7 @@ def to_s
     end
 
     # four parts: day-of-week date time time-zone
-    TIMESTAMP_RX = /\S+\s+\S+\s+\S+\s\S+/
+    TIMESTAMP_RX = /\S+\s+\S+\s+\S+\s\S+/.freeze
     private_constant :TIMESTAMP_RX
 
     # Array of system's boots registered in the journal.
@@ -95,11 +96,13 @@ def to_s
     def self.boots
       lines = Journalctl.new({ "list-boots" => nil, "quiet" => nil }, []).output.lines
       lines.map do |line|
+        # rubocop: disable Style/GuardClause
+        #
         # The 'journalctl --list-boots' output looks like this
         # (slightly stripped down, see test/data for full-length examples)
         # -1 a07ac0f240 Sun 2014-12-14 16:50:09 CET Mon 2015-01-26 19:18:43 CET
         #  0 24a9a83ecf Mon 2015-01-26 19:55:33 CET Mon 2015-01-26 20:05:16 CET
-        if line.strip =~ /^\s*(-*\d+)\s+(\w+)\s+(#{TIMESTAMP_RX})[— ](#{TIMESTAMP_RX})$/
+        if line.strip =~ /^\s*(-*\d+)\s+(\w+)\s+(#{TIMESTAMP_RX})[— ]+(#{TIMESTAMP_RX})$/
           {
             id:         Regexp.last_match[2],
             offset:     Regexp.last_match[1],
@@ -111,6 +114,7 @@ def self.boots
         else
           raise "Unexpected output for journalctl --list-boots: #{line}"
         end
+        # rubocop: enable Style/GuardClause
       end
     end
 
@@ -133,7 +137,7 @@ def calculate_options
         end
       end
       # Remove empty time arguments
-      @journalctl_options.reject! { |_, v| v.nil? }
+      @journalctl_options.compact!
 
       # Add filters...
       @journalctl_options.merge!(@filters)
diff --git a/src/lib/y2journal/query_dialog.rb b/src/lib/y2journal/query_dialog.rb
index b14e83f..43e6464 100644
--- a/src/lib/y2journal/query_dialog.rb
+++ b/src/lib/y2journal/query_dialog.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
@@ -111,6 +113,7 @@ def query_from_widgets
         name = filter[:name]
         # Skip if the checkbox is not checked
         next unless Yast::UI.QueryWidget(Id(name), :Value)
+
         # Read the widget...
         value = widget_to_filter(name, filter[:multiple])
         # ...discarding empty values
@@ -246,7 +249,7 @@ def filter_to_string(name)
     def widget_to_filter(name, multiple)
       value = Yast::UI.QueryWidget(Id(:"#{name}_value"), :Value)
       if multiple
-        value.split(" ")
+        value.split
       else
         value
       end
diff --git a/src/lib/y2journal/query_presenter.rb b/src/lib/y2journal/query_presenter.rb
index 94c6aed..9b9c2a2 100644
--- a/src/lib/y2journal/query_presenter.rb
+++ b/src/lib/y2journal/query_presenter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
@@ -28,9 +30,10 @@ class QueryPresenter < SimpleDelegator
     extend Yast::I18n
     textdomain "journal"
 
-    TIME_FORMAT = "%b %d %H:%M:%S".freeze
+    TIME_FORMAT = "%b %d %H:%M:%S"
 
     def initialize(query = nil)
+      super
       textdomain "journal"
 
       if !query
@@ -69,6 +72,7 @@ def filters_description
         QueryPresenter.filters.each do |filter|
           value = filters[filter[:name]]
           next if value.nil?
+
           value = value.join(" ") if filter[:multiple]
           descriptions << "#{filter[:label]} (#{value})"
         end
@@ -160,7 +164,7 @@ def self.filters
     # Default value for interval[:since]
     def self.default_since
       # 24 hours ago
-      Time.now - 24 * 60 * 60
+      Time.now - (24 * 60 * 60)
     end
 
     # Default value for interval[:until]
diff --git a/src/lib/y2journal/time_helpers.rb b/src/lib/y2journal/time_helpers.rb
index 45514df..74a39d4 100644
--- a/src/lib/y2journal/time_helpers.rb
+++ b/src/lib/y2journal/time_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/test/cli_test.rb b/test/cli_test.rb
index 37a6fbb..eed510e 100644
--- a/test/cli_test.rb
+++ b/test/cli_test.rb
@@ -1,4 +1,6 @@
 #! /usr/bin/rspec
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/test/data/list-boots-11.out b/test/data/list-boots-11.out
index d30cca3..86c7e5e 100644
--- a/test/data/list-boots-11.out
+++ b/test/data/list-boots-11.out
@@ -1,11 +1,11 @@
- -10 f02631731f744344859a5b7222d815d6 Wed 2014-10-01 21:12:23 CEST—Sun 2014-10-05 20:36:49 CEST
+ -10 f02631731f744344859a5b7222d815d6 Wed 2014-10-01 21:12:23 CEST Sun 2014-10-05 20:36:49 CEST
   -9 c89b2b67d5724a3d99bc23dbfb2d0881 Sun 2014-10-05 21:12:23 CEST—Tue 2014-10-14 20:36:49 CEST
-  -8 114cf1cb4232492fa7ac7af4b5de17ce Tue 2014-10-14 20:39:33 CEST—Wed 2014-10-29 19:45:53 CET
-  -7 f416bdfe857440bd999734c82c851d28 Wed 2014-10-29 19:47:11 CET—Fri 2014-10-31 07:28:15 CET
-  -6 32b9544f82a640879955630fe7810922 Wed 2014-11-19 11:39:53 CET—Sat 2014-11-22 12:37:07 CET
-  -5 13a9100a19a640c8878b6487587c2079 Sat 2014-11-22 12:38:19 CET—Sun 2014-11-23 08:51:30 CET
-  -4 334317f877514e93b7e8b27a6517361a Sun 2014-11-23 09:06:53 CET—Mon 2014-11-24 08:11:31 CET
-  -3 0dc4f86993a943d9bb862835c2b3dc36 Mon 2014-11-24 08:21:46 CET—Fri 2014-12-05 17:08:09 CET
-  -2 d18711cf465d46729f5c5bd6bf44ce05 Fri 2014-12-05 17:09:10 CET—Sun 2014-12-14 16:41:53 CET
-  -1 a07ac085b07d43d99b09ee9d146af240 Sun 2014-12-14 16:50:09 CET—Mon 2015-01-26 19:18:43 CET
-   0 24a9a89c43d34f859399f7994a233ecf Mon 2015-01-26 19:55:33 CET—Mon 2015-01-26 20:05:16 CET
+  -8 114cf1cb4232492fa7ac7af4b5de17ce Tue 2014-10-14 20:39:33 CEST Wed 2014-10-29 19:45:53 CET
+  -7 f416bdfe857440bd999734c82c851d28 Wed 2014-10-29 19:47:11 CET  Fri 2014-10-31 07:28:15 CET
+  -6 32b9544f82a640879955630fe7810922 Wed 2014-11-19 11:39:53 CET  Sat 2014-11-22 12:37:07 CET
+  -5 13a9100a19a640c8878b6487587c2079 Sat 2014-11-22 12:38:19 CET  Sun 2014-11-23 08:51:30 CET
+  -4 334317f877514e93b7e8b27a6517361a Sun 2014-11-23 09:06:53 CET  Mon 2014-11-24 08:11:31 CET
+  -3 0dc4f86993a943d9bb862835c2b3dc36 Mon 2014-11-24 08:21:46 CET  Fri 2014-12-05 17:08:09 CET
+  -2 d18711cf465d46729f5c5bd6bf44ce05 Fri 2014-12-05 17:09:10 CET  Sun 2014-12-14 16:41:53 CET
+  -1 a07ac085b07d43d99b09ee9d146af240 Sun 2014-12-14 16:50:09 CET  Mon 2015-01-26 19:18:43 CET
+   0 24a9a89c43d34f859399f7994a233ecf Mon 2015-01-26 19:55:33 CET  Mon 2015-01-26 20:05:16 CET
diff --git a/test/entries_dialog_test.rb b/test/entries_dialog_test.rb
index 2831d2b..0effe06 100644
--- a/test/entries_dialog_test.rb
+++ b/test/entries_dialog_test.rb
@@ -1,4 +1,6 @@
 #! /usr/bin/rspec
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/test/entry_presenter_test.rb b/test/entry_presenter_test.rb
index 99167cf..11bd05d 100755
--- a/test/entry_presenter_test.rb
+++ b/test/entry_presenter_test.rb
@@ -1,4 +1,6 @@
 #! /usr/bin/rspec
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/test/entry_test.rb b/test/entry_test.rb
index caad38b..24d0ff2 100755
--- a/test/entry_test.rb
+++ b/test/entry_test.rb
@@ -1,4 +1,6 @@
 #! /usr/bin/rspec
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/test/journalctl_test.rb b/test/journalctl_test.rb
index 1e4af62..54b9b1b 100755
--- a/test/journalctl_test.rb
+++ b/test/journalctl_test.rb
@@ -1,4 +1,6 @@
 #! /usr/bin/rspec
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/test/query_dialog_test.rb b/test/query_dialog_test.rb
index b478151..4f8a70e 100755
--- a/test/query_dialog_test.rb
+++ b/test/query_dialog_test.rb
@@ -1,4 +1,6 @@
 #! /usr/bin/rspec
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
@@ -36,7 +38,7 @@ def property(id, property)
     #   changes.
     def send_user_input(value, pre_hook: nil)
       expect(Yast::UI).to receive(:UserInput) do
-        pre_hook.call if pre_hook
+        pre_hook&.call
         value
       end
     end
diff --git a/test/query_presenter_test.rb b/test/query_presenter_test.rb
index 6a1e9d9..1e3e0a5 100755
--- a/test/query_presenter_test.rb
+++ b/test/query_presenter_test.rb
@@ -1,4 +1,6 @@
 #! /usr/bin/rspec
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/test/query_test.rb b/test/query_test.rb
index b80e9d9..ded90ef 100755
--- a/test/query_test.rb
+++ b/test/query_test.rb
@@ -1,4 +1,6 @@
 #! /usr/bin/rspec
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
diff --git a/test/spec_helper.rb b/test/spec_helper.rb
index 49c0eef..3a54fd4 100644
--- a/test/spec_helper.rb
+++ b/test/spec_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Copyright (c) 2014 SUSE LLC.
 #  All Rights Reserved.
 
@@ -17,8 +19,8 @@
 #  you may find current contact information at www.suse.com
 
 # Set the paths
-SRC_PATH = File.expand_path("../../src", __FILE__)
-DATA_PATH = File.join(File.expand_path(File.dirname(__FILE__)), "data")
+SRC_PATH = File.expand_path("../src", __dir__)
+DATA_PATH = File.join(__dir__, "data")
 ENV["Y2DIR"] = SRC_PATH
 
 require "yast"


Reviews:
user: login: mvidner
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-29T10:02:20Z
user: login: mvidner
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-29T10:17:59Z
user: login: shundhammer
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T10:18:41Z
user: login: mvidner
body: LGTM, thank you!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-29T10:19:01Z

Review comments:
diff_hunk: @@ -1,3 +1,11 @@
+-------------------------------------------------------------------
+Sun Apr 27 11:50:04 UTC 2025 - Stefan Hundhammer <shundhammer@suse.com>
+
+- Fixed regexp for changed 'journalctl --list-boots' output:
+  Now taking daylight savings time on/off into account
+  #1241904
path: package/yast2-journal.changes
user: login: mvidner
body: ```suggestion
  (bsc#1241904)
```
created_at: 2025-04-29T10:02:19Z
author_association: MEMBER
diff_hunk: @@ -25,9 +27,10 @@ module Y2Journal
   class EntryPresenter < SimpleDelegator
     include Yast::I18n
 
-    TIME_FORMAT = "%b %d %H:%M:%S".freeze
+    TIME_FORMAT = "%b %d %H:%M:%S"
 
     def initialize(entry)
+      super
path: src/lib/y2journal/entry_presenter.rb
user: login: mvidner
body: BTW this seems to duplicate `__setobj__` below, but [`SimpleDelegator` documentation](https://ruby-doc.org/3.4.1/stdlibs/delegate/SimpleDelegator.html) is awful, so let's leave this as it is
created_at: 2025-04-29T10:17:59Z
author_association: MEMBER
diff_hunk: @@ -25,9 +27,10 @@ module Y2Journal
   class EntryPresenter < SimpleDelegator
     include Yast::I18n
 
-    TIME_FORMAT = "%b %d %H:%M:%S".freeze
+    TIME_FORMAT = "%b %d %H:%M:%S"
 
     def initialize(entry)
+      super
path: src/lib/y2journal/entry_presenter.rb
user: login: shundhammer
body: Rubocop complained about it.
created_at: 2025-04-29T10:18:41Z
author_association: CONTRIBUTOR

PR comments:
user: login: coveralls
created_at: 2025-04-27T12:01:17Z
body: 
[![Coverage Status](https://coveralls.io/builds/73429905/badge)](https://coveralls.io/builds/73429905)

coverage: 85.106% (+0.04%) from 85.067%
when pulling **ab05b46601cf29acdef484b990807457e219ec9b on huha-fix-regexp**
into **56403ef743decf5a5d236c460045e90d085dc6a9 on master**.

author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-29T10:39:54Z
body: :white_check_mark: Autosubmission job [#14729211846](https://github.com/yast/yast-journal/actions/runs/14729211846) successfully finished
:white_check_mark: Created submit request [#1273394](https://build.opensuse.org/request/show/1273394)
author_association: NONE