diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb
index 31675a5816353bc5133ccae397faece012c4cac8..0c15c4d0d3f633018c11a007bf600b6637883994 100644
--- a/app/controllers/concerns/membership_actions.rb
+++ b/app/controllers/concerns/membership_actions.rb
@@ -16,7 +16,7 @@ def update
     member_data = if member.expires?
                     {
                       expires_soon: member.expires_soon?,
-                      expires_at_formatted: member.expires_at.to_time.in_time_zone.to_s(:medium)
+                      expires_at_formatted: member.expires_at.to_time.in_time_zone.to_fs(:medium)
                     }
                   else
                     {}
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index e247577aed034ee694d56d36d8091bebc3f7193f..e921e9bae4d791bc345bf5e76d9aa5b2c66b8258 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -43,14 +43,10 @@ def sidebar_milestone_remaining_days(milestone)
     due_date_with_remaining_days(milestone[:due_date], milestone[:start_date])
   end
 
-  def sidebar_due_date_tooltip_label(due_date)
-    [_('Due date'), due_date_with_remaining_days(due_date)].compact.join('<br/>')
-  end
-
   def due_date_with_remaining_days(due_date, start_date = nil)
     return unless due_date
 
-    "#{due_date.to_s(:medium)} (#{remaining_days_in_words(due_date, start_date)})"
+    "#{due_date.to_fs(:medium)} (#{remaining_days_in_words(due_date, start_date)})"
   end
 
   def multi_label_name(current_labels, default_label)
diff --git a/app/helpers/time_helper.rb b/app/helpers/time_helper.rb
index cb6f60ab79b815041bd1f4bddbf2c6bd8dcb2993..ad473875a53f57ff2a3715dea8ac0af591e47bd2 100644
--- a/app/helpers/time_helper.rb
+++ b/app/helpers/time_helper.rb
@@ -17,10 +17,6 @@ def time_interval_in_words(interval_in_seconds)
     end
   end
 
-  def date_from_to(from, to)
-    "#{from.to_s(:short)} - #{to.to_s(:short)}"
-  end
-
   def duration_in_numbers(duration_in_seconds)
     seconds = duration_in_seconds % 1.minute
     minutes = (duration_in_seconds / 1.minute) % (1.hour / 1.minute)
diff --git a/app/helpers/timeboxes_helper.rb b/app/helpers/timeboxes_helper.rb
index 66c9011fbcc18ac9745584e67444ec50133ca599..cb6ed059ec9f9764515136fd63c642ef7983b2af 100644
--- a/app/helpers/timeboxes_helper.rb
+++ b/app/helpers/timeboxes_helper.rb
@@ -109,7 +109,7 @@ def milestone_time_for(date, date_type)
       content = [
         title,
         "<br />",
-        date.to_s(:medium),
+        date.to_fs(:medium),
         "(#{time_ago} #{state})"
       ].join(" ")
 
@@ -172,7 +172,7 @@ def recent_releases_with_counts(milestone, user)
 
   def milestone_tooltip_due_date(milestone)
     if milestone.due_date
-      "#{milestone.due_date.to_s(:medium)} (#{remaining_days_in_words(milestone.due_date, milestone.start_date)})"
+      "#{milestone.due_date.to_fs(:medium)} (#{remaining_days_in_words(milestone.due_date, milestone.start_date)})"
     else
       _('Milestone')
     end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index c8002c437a9e66c07e6b723e600569fd7a47179b..893cf8851c080697f10b02d63a10821afdb2339c 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -12,7 +12,7 @@ def user_clear_status_at(user)
     # The user.status can be nil when the user has no status, so we need to protect against that case.
     # iso8601 is the official RFC supported format for frontend parsing of date:
     # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
-    user.status&.clear_status_at&.to_s(:iso8601)
+    user.status&.clear_status_at&.to_fs(:iso8601)
   end
 
   def user_link(user)
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
index 4f2ea58f36d869ad07e8dd17285bfb287c8fbbee..7968fe1cd86f5372415ab19548eab05ecca5d707 100644
--- a/app/models/concerns/milestoneish.rb
+++ b/app/models/concerns/milestoneish.rb
@@ -90,9 +90,9 @@ def upcoming?
   def expires_at
     if due_date
       if due_date.past?
-        "expired on #{due_date.to_s(:medium)}"
+        "expired on #{due_date.to_fs(:medium)}"
       else
-        "expires on #{due_date.to_s(:medium)}"
+        "expires on #{due_date.to_fs(:medium)}"
       end
     end
   end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 5af0216a3ca8501fb6fed42898947e9c76094ea2..b59b22c10c4c3d35191e03027e0e52b7c1631e9a 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -351,7 +351,7 @@ def deployed_at
   end
 
   def formatted_deployment_time
-    deployed_at&.to_time&.in_time_zone&.to_s(:medium)
+    deployed_at&.to_time&.in_time_zone&.to_fs(:medium)
   end
 
   def deployed_by
diff --git a/app/serializers/lfs_file_lock_entity.rb b/app/serializers/lfs_file_lock_entity.rb
index 7961c4e666b374492f8c13ae5d14aca2d7d0f760..787d201d0a1af99ca942eb9e62607e1ac486f300 100644
--- a/app/serializers/lfs_file_lock_entity.rb
+++ b/app/serializers/lfs_file_lock_entity.rb
@@ -5,7 +5,7 @@ class LfsFileLockEntity < Grape::Entity
 
   expose :path
   expose(:id) { |entity| entity.id.to_s }
-  expose(:created_at, as: :locked_at) { |entity| entity.created_at.to_s(:iso8601) }
+  expose(:created_at, as: :locked_at) { |entity| entity.created_at.to_fs(:iso8601) }
 
   expose :owner do
     expose(:name) { |entity| entity.user&.name }
diff --git a/app/services/issues/export_csv_service.rb b/app/services/issues/export_csv_service.rb
index 9e524d90505fc19b94252032736fb1c386a1350b..99c0e9f1a37a5e3bf7c7a45ab0a9ac5df6fc3af2 100644
--- a/app/services/issues/export_csv_service.rb
+++ b/app/services/issues/export_csv_service.rb
@@ -34,14 +34,14 @@ def header_to_value_hash
         'Assignee Username' => -> (issue) { issue.assignees.map(&:username).join(', ') },
         'Confidential' => -> (issue) { issue.confidential? ? 'Yes' : 'No' },
         'Locked' => -> (issue) { issue.discussion_locked? ? 'Yes' : 'No' },
-        'Due Date' => -> (issue) { issue.due_date&.to_s(:csv) },
-        'Created At (UTC)' => -> (issue) { issue.created_at&.to_s(:csv) },
-        'Updated At (UTC)' => -> (issue) { issue.updated_at&.to_s(:csv) },
-        'Closed At (UTC)' => -> (issue) { issue.closed_at&.to_s(:csv) },
+        'Due Date' => -> (issue) { issue.due_date&.to_fs(:csv) },
+        'Created At (UTC)' => -> (issue) { issue.created_at&.to_fs(:csv) },
+        'Updated At (UTC)' => -> (issue) { issue.updated_at&.to_fs(:csv) },
+        'Closed At (UTC)' => -> (issue) { issue.closed_at&.to_fs(:csv) },
         'Milestone' => -> (issue) { issue.milestone&.title },
         'Weight' => -> (issue) { issue.weight },
         'Labels' => -> (issue) { issue_labels(issue) },
-        'Time Estimate' => ->(issue) { issue.time_estimate.to_s(:csv) },
+        'Time Estimate' => ->(issue) { issue.time_estimate.to_fs(:csv) },
         'Time Spent' => -> (issue) { issue_time_spent(issue) }
       }
     end
diff --git a/app/services/system_notes/time_tracking_service.rb b/app/services/system_notes/time_tracking_service.rb
index b7a2afbaf156bbebf88a166ed4e6a5dad43f56bc..f9084ed67d3bfd6d45cf10668198d11130faea47 100644
--- a/app/services/system_notes/time_tracking_service.rb
+++ b/app/services/system_notes/time_tracking_service.rb
@@ -147,9 +147,9 @@ def message_for_changed_date(changed_dates, date_key)
       readable_date = date_key.humanize.downcase
 
       if changed_date.nil?
-        "removed #{readable_date} #{changed_dates[date_key].first.to_s(:long)}"
+        "removed #{readable_date} #{changed_dates[date_key].first.to_fs(:long)}"
       else
-        "changed #{readable_date} to #{changed_date.to_s(:long)}"
+        "changed #{readable_date} to #{changed_date.to_fs(:long)}"
       end
     end
 
diff --git a/app/services/work_items/export_csv_service.rb b/app/services/work_items/export_csv_service.rb
index ee20a2832ce886df4cab2bb424990f9d0390b438..74bc1f526bffef95b2e259708f2086d9a26418d1 100644
--- a/app/services/work_items/export_csv_service.rb
+++ b/app/services/work_items/export_csv_service.rb
@@ -28,7 +28,7 @@ def header_to_value_hash
         'Type' => ->(work_item) { work_item.work_item_type.name },
         'Author' => 'author_name',
         'Author Username' => ->(work_item) { work_item.author.username },
-        'Created At (UTC)' => ->(work_item) { work_item.created_at.to_s(:csv) }
+        'Created At (UTC)' => ->(work_item) { work_item.created_at.to_fs(:csv) }
       }
     end
 
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 4ba6912690650ec38009d2463cdc3392164cad3f..5f5f6c986639fe4541c618117d86989260f69741 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -43,7 +43,7 @@
           %li
             %span.light= _('Created on:')
             %strong
-              = @group.created_at.to_s(:medium)
+              = @group.created_at.to_fs(:medium)
 
           %li
             %span.light= _('ID:')
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 8eb72fa281e0c8fa5854f9ebdaedbf6d29bc61c9..0637b0eae472462ef8c194e47d733c114f4b7356 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -60,7 +60,7 @@
             %span.light
               = _('Created on:')
             %strong
-              = @project.created_at.to_s(:medium)
+              = @project.created_at.to_fs(:medium)
 
           %li{ class: 'gl-px-5!' }
             %span.light
@@ -158,10 +158,10 @@
               = _("This repository has never been checked.")
             - elsif @project.last_repository_check_failed?
               - failed_message = _("This repository was last checked %{last_check_timestamp}. The check %{strong_start}failed.%{strong_end} See the 'repocheck.log' file for error messages.")
-              - failed_message = failed_message % { last_check_timestamp: @project.last_repository_check_at.to_s(:medium), strong_start: "<strong class='cred'>", strong_end: "</strong>" }
+              - failed_message = failed_message % { last_check_timestamp: @project.last_repository_check_at.to_fs(:medium), strong_start: "<strong class='cred'>", strong_end: "</strong>" }
               = failed_message.html_safe
             - else
-              = _("This repository was last checked %{last_check_timestamp}. The check passed.") % { last_check_timestamp: @project.last_repository_check_at.to_s(:medium) }
+              = _("This repository was last checked %{last_check_timestamp}. The check passed.") % { last_check_timestamp: @project.last_repository_check_at.to_fs(:medium) }
 
             = link_to sprite_icon('question-o'), help_page_path('administration/repository_checks')
 
diff --git a/app/views/admin/users/_profile.html.haml b/app/views/admin/users/_profile.html.haml
index b4f61a1b66523f1514dda537af1c79b16e14d323..bb89b5baf28cf9887e8655c5896156ff31110f71 100644
--- a/app/views/admin/users/_profile.html.haml
+++ b/app/views/admin/users/_profile.html.haml
@@ -5,7 +5,7 @@
     %ul.content-list
       %li
         %span.light= _('Member since')
-        %strong= user.created_at.to_s(:medium)
+        %strong= user.created_at.to_fs(:medium)
       - unless user.public_email.blank?
         %li
           %span.light= _('E-mail:')
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index ea6525e1b96a9b526ae08bce9635e3d4565d9266..d793dcaccd51d3917b6006a2876ab58612c5344e 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -86,12 +86,12 @@
           %li
             %span.light= _('Member since:')
             %strong
-              = @user.created_at.to_s(:medium)
+              = @user.created_at.to_fs(:medium)
           - if @user.confirmed_at
             %li
               %span.light= _('Confirmed at:')
               %strong
-                = @user.confirmed_at.to_s(:medium)
+                = @user.confirmed_at.to_fs(:medium)
           - else
             %li
               %span.ligh= _('Confirmed:')
@@ -106,7 +106,7 @@
           %li
             %span.light= _('Current sign-in at:')
             %strong
-              = @user.current_sign_in_at&.to_s(:medium) || _('never')
+              = @user.current_sign_in_at&.to_fs(:medium) || _('never')
 
           %li
             %span.light= _('Last sign-in IP:')
@@ -116,7 +116,7 @@
           %li
             %span.light= _('Last sign-in at:')
             %strong
-              = @user.last_sign_in_at&.to_s(:medium) || _('never')
+              = @user.last_sign_in_at&.to_fs(:medium) || _('never')
 
           %li
             %span.light= _('Sign-in count:')
diff --git a/app/views/events/_event_push.atom.haml b/app/views/events/_event_push.atom.haml
index c3786d7c16d87e45fcf861f0a49c2c1f1fb3b26c..51b60fe01523b74ee4a7dc1b4003b513879e3b00 100644
--- a/app/views/events/_event_push.atom.haml
+++ b/app/views/events/_event_push.atom.haml
@@ -6,7 +6,7 @@
     = link_to "(#{truncate_sha(event.commit_id)})", event_url if event_url
     %i
       at
-      = event.created_at.to_s(:short)
+      = event.created_at.to_fs(:short)
   - unless event.rm_ref?
     .blockquote= markdown(escape_once(event.commit_title), pipeline: :atom, project: event.project, author: event.author)
     - if event.commits_count > 1
diff --git a/app/views/notify/issue_due_email.html.haml b/app/views/notify/issue_due_email.html.haml
index 9dd501022dd4dbf383d77677dce564b9e0a8ab68..f1959ce2557a1e810052c32326c14f740e139a90 100644
--- a/app/views/notify/issue_due_email.html.haml
+++ b/app/views/notify/issue_due_email.html.haml
@@ -5,7 +5,7 @@
   %p
     = assignees_label(@issue)
 %p
-  = sprintf(s_('Notify|This issue is due on: %{issue_due_date}'), { issue_due_date: @issue.due_date.to_s(:medium) }).html_safe
+  = sprintf(s_('Notify|This issue is due on: %{issue_due_date}'), { issue_due_date: @issue.due_date.to_fs(:medium) }).html_safe
 
 - if @issue.description
   .md
diff --git a/app/views/notify/repository_push_email.html.haml b/app/views/notify/repository_push_email.html.haml
index d493f9d5d9839aeaecac8e76f4d4185985fab65e..199865ba644ccf7d9d738882581a36ca28c839a5 100644
--- a/app/views/notify/repository_push_email.html.haml
+++ b/app/views/notify/repository_push_email.html.haml
@@ -19,7 +19,7 @@
       %li
         %strong= link_to(commit.short_id, project_commit_url(@message.project, commit))
         %div
-          = html_escape(s_('Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}')) % {committed_by_start: '<span>'.html_safe, author_name: commit.author_name, committed_by_end: '</span>'.html_safe, committed_at_start: '<i>'.html_safe, committed_date: commit.committed_date.to_s(:iso8601), committed_at_end: '</i>'.html_safe}
+          = html_escape(s_('Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}')) % {committed_by_start: '<span>'.html_safe, author_name: commit.author_name, committed_by_end: '</span>'.html_safe, committed_at_start: '<i>'.html_safe, committed_date: commit.committed_date.to_fs(:iso8601), committed_at_end: '</i>'.html_safe}
         %pre.commit-message
           = commit.safe_message
 
diff --git a/app/views/notify/repository_push_email.text.haml b/app/views/notify/repository_push_email.text.haml
index 2ba0a2cf4abb4d91743954900f93ab57433f7fa9..38a439864b7351fdd7901515a2cb2700d995d031 100644
--- a/app/views/notify/repository_push_email.text.haml
+++ b/app/views/notify/repository_push_email.text.haml
@@ -8,7 +8,7 @@
     \
   = @message.reverse_compare? ? "Deleted commits:" : "Commits:"
   - @message.commits.each do |commit|
-    #{commit.short_id} by #{commit.author_name} at #{commit.committed_date.to_s(:iso8601)}
+    #{commit.short_id} by #{commit.author_name} at #{commit.committed_date.to_fs(:iso8601)}
     #{commit.safe_message}
     \- - - - -
   \
diff --git a/app/views/profiles/keys/_key_details.html.haml b/app/views/profiles/keys/_key_details.html.haml
index 4f3d97fb90c60eb714086358151bf1bb906e00ab..d835366348a91333b750c29e4be851380b945d0d 100644
--- a/app/views/profiles/keys/_key_details.html.haml
+++ b/app/views/profiles/keys/_key_details.html.haml
@@ -14,7 +14,7 @@
             %strong= ssh_key_usage_types.invert[@key.usage_type]
           %li
             %span.light= _('Created on:')
-            %strong= @key.created_at.to_s(:medium)
+            %strong= @key.created_at.to_fs(:medium)
           %li
             %span.light= _('Expires:')
             %strong= @key.expires_at.try(:to_s, :medium) || _('Never')
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 461164e1ae91313c3fe3ccbcea950ca2dd1d78e3..bfd6b133a937e5fd2bc9f6f7661191edb4f33225 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -101,7 +101,7 @@
                     - else
                       %span.gl-text-gray-500
                         = _("no name set")
-                  %td= registration[:created_at].to_date.to_s(:medium)
+                  %td= registration[:created_at].to_date.to_fs(:medium)
                   %td
                     = render Pajamas::ButtonComponent.new(variant: :danger,
                       href: registration[:delete_path],
diff --git a/app/views/projects/issues/service_desk/_issue.html.haml b/app/views/projects/issues/service_desk/_issue.html.haml
index 04ea6103b832b577296840bd8d7151477610f34a..5b98712d3eb2a8d434980ef041ff24ca23b94b30 100644
--- a/app/views/projects/issues/service_desk/_issue.html.haml
+++ b/app/views/projects/issues/service_desk/_issue.html.haml
@@ -33,7 +33,7 @@
           %span.issuable-due-date.d-none.d-sm-inline-block.has-tooltip{ class: "#{'cred' if issue.overdue? && !issue.closed?}", title: _('Due date') }
             &nbsp;
             = sprite_icon('calendar')
-            = issue.due_date.to_s(:medium)
+            = issue.due_date.to_fs(:medium)
 
         = render_if_exists "projects/issues/issue_weight", issue: issue
         = render_if_exists "projects/issues/health_status", issue: issue
diff --git a/app/views/shared/deploy_tokens/_table.html.haml b/app/views/shared/deploy_tokens/_table.html.haml
index a7bf3bfb81e655c52da68e0c4d704a44afed7013..3827ecf73a47a79123ad54b433c184482a19accf 100644
--- a/app/views/shared/deploy_tokens/_table.html.haml
+++ b/app/views/shared/deploy_tokens/_table.html.haml
@@ -16,7 +16,7 @@
           %tr
             %td= token.name
             %td= token.username
-            %td= token.created_at.to_date.to_s(:medium)
+            %td= token.created_at.to_date.to_fs(:medium)
             %td
               - if token.expires?
                 %span{ class: ('text-warning' if token.expires_soon?) }
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index 376e51a6b1556ec4c0ca227e97972a132a4e861f..c86993f5b776b8644ecbc0a8aac5628f64bba0e0 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -43,7 +43,7 @@
             = _("Given access %{time_ago}").html_safe % { time_ago: time_ago_with_tooltip(member.created_at) }
           %span.js-expires-in{ class: ('gl-display-none' unless member.expires?) }
             &middot;
-            %span.js-expires-in-text{ class: "has-tooltip#{' text-warning' if member.expires_soon?}", title: (member.expires_at.to_time.in_time_zone.to_s(:medium) if member.expires?) }
+            %span.js-expires-in-text{ class: "has-tooltip#{' text-warning' if member.expires_soon?}", title: (member.expires_at.to_time.in_time_zone.to_fs(:medium) if member.expires?) }
               - if member.expires?
                 - preposition = current_user.time_display_relative ? '' : 'on'
                 = _("Expires %{preposition} %{expires_at}").html_safe % { expires_at: time_ago_with_tooltip(member.expires_at), preposition: preposition }
diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml
index 5477b9395eabd0b78261a72feca43475f1dc9cb8..1b0eeb424c208447eb6466dc26c83af8d8ace539 100644
--- a/app/views/shared/milestones/_sidebar.html.haml
+++ b/app/views/shared/milestones/_sidebar.html.haml
@@ -26,7 +26,7 @@
       .value
         %span.value-content{ data: { qa_selector: 'start_date_content' } }
           - if milestone.start_date
-            %span.bold= milestone.start_date.to_s(:medium)
+            %span.bold= milestone.start_date.to_fs(:medium)
           - else
             %span.no-value= s_('MilestoneSidebar|No start date')
 
@@ -63,7 +63,7 @@
       .value.hide-collapsed
         %span.value-content{ data: { qa_selector: 'due_date_content' } }
           - if milestone.due_date
-            %span.bold= milestone.due_date.to_s(:medium)
+            %span.bold= milestone.due_date.to_fs(:medium)
           - else
             %span.no-value= s_('MilestoneSidebar|No due date')
         - remaining_days = remaining_days_in_words(milestone.due_date, milestone.start_date)
diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml
index 3571031fbfa5189ee639cb48e6093fc6595876b0..e98dd87a3075cd51858522899a2eb5afe67f85ec 100644
--- a/app/views/users/calendar_activities.html.haml
+++ b/app/views/users/calendar_activities.html.haml
@@ -1,5 +1,5 @@
 %h4.prepend-top-20
-  = html_escape(_("Contributions for %{calendar_date}")) % { calendar_date: tag.strong(@calendar_date.to_s(:medium)) }
+  = html_escape(_("Contributions for %{calendar_date}")) % { calendar_date: tag.strong(@calendar_date.to_fs(:medium)) }
 
 - if @events.any?
   %ul.bordered-list
diff --git a/config/initializers/00_deprecations.rb b/config/initializers/00_deprecations.rb
index c45f7ab7a5a96be85b3875d498a274326f94e68f..3d6a649117609473889d187b5c034ee85296bed2 100644
--- a/config/initializers/00_deprecations.rb
+++ b/config/initializers/00_deprecations.rb
@@ -42,7 +42,9 @@
     # https://gitlab.com/gitlab-org/gitlab/-/issues/410086
     /Using `return`, `break` or `throw` to exit a transaction block/,
     # https://gitlab.com/gitlab-org/gitlab/-/issues/414556
-    /Merging .* no longer maintain both conditions, and will be replaced by the latter in Rails 7\.0/
+    /Merging .* no longer maintain both conditions, and will be replaced by the latter in Rails 7\.0/,
+    # https://gitlab.com/gitlab-org/gitlab/-/issues/415890
+    /(Date|Time|TimeWithZone)#to_s.+ is deprecated/
   ]
 
   view_component_3_warnings = [
diff --git a/ee/app/controllers/groups/seat_usage_controller.rb b/ee/app/controllers/groups/seat_usage_controller.rb
index e6e477d882fd5bdd836879337d2c9d29a371a748..3975d7dcb855d435e5df0a99f71af9620e52d794 100644
--- a/ee/app/controllers/groups/seat_usage_controller.rb
+++ b/ee/app/controllers/groups/seat_usage_controller.rb
@@ -39,7 +39,7 @@ def redirect_to_seat_usage_tab
   end
 
   def csv_filename
-    "seat-usage-export-#{Time.current.to_s(:number)}.csv"
+    "seat-usage-export-#{Time.current.to_fs(:number)}.csv"
   end
 
   def verify_top_level_group
diff --git a/ee/app/helpers/ee/projects_helper.rb b/ee/app/helpers/ee/projects_helper.rb
index 26e4040f7fb324f5a58eead3aca658a642cc85fd..ab7be46bff80d3bfeff1dba23846a046b4d41e15 100644
--- a/ee/app/helpers/ee/projects_helper.rb
+++ b/ee/app/helpers/ee/projects_helper.rb
@@ -322,7 +322,7 @@ def security_dashboard_pipeline_data(project)
         pipeline: {
           id: pipeline.id,
           path: pipeline_path(pipeline),
-          created_at: pipeline.created_at.to_s(:iso8601),
+          created_at: pipeline.created_at.to_fs(:iso8601),
           has_warnings: pipeline.has_security_report_ingestion_warnings?.to_s,
           has_errors: pipeline.has_security_report_ingestion_errors?.to_s,
           security_builds: {
diff --git a/ee/app/models/iteration.rb b/ee/app/models/iteration.rb
index 8c47f25d671c777d0c4555f39df562664620527c..130a034f7020992a00cb585dea5e6a7db9b208f7 100644
--- a/ee/app/models/iteration.rb
+++ b/ee/app/models/iteration.rb
@@ -177,7 +177,7 @@ def contains_digits?(query)
   end
 
   def period
-    "#{start_date.to_s(:medium)} - #{due_date.to_s(:medium)}"
+    "#{start_date.to_fs(:medium)} - #{due_date.to_fs(:medium)}"
   end
 
   def display_text
diff --git a/ee/app/presenters/epic_presenter.rb b/ee/app/presenters/epic_presenter.rb
index fbb94b644b3945034a796858bcedd3959d72f462..f6524c37c7cb3ce15ccf833a6bc0f581bf6a2695 100644
--- a/ee/app/presenters/epic_presenter.rb
+++ b/ee/app/presenters/epic_presenter.rb
@@ -139,7 +139,7 @@ def epic_ancestors(epics)
         title: epic.title,
         url: url_builder.epic_path(epic),
         state: epic.state,
-        human_readable_end_date: epic.end_date&.to_s(:medium),
+        human_readable_end_date: epic.end_date&.to_fs(:medium),
         human_readable_timestamp: remaining_days_in_words(epic.end_date, epic.start_date)
       }
     end
diff --git a/ee/app/serializers/epic_base_entity.rb b/ee/app/serializers/epic_base_entity.rb
index de8c0bfd9751d1009feb3dea74eae8d60e594f67..02a7310f2aa3c434fe5d1660e9d618159413dd4c 100644
--- a/ee/app/serializers/epic_base_entity.rb
+++ b/ee/app/serializers/epic_base_entity.rb
@@ -12,7 +12,7 @@ class EpicBaseEntity < Grape::Entity
   end
   expose :group_id
   expose :human_readable_end_date, if: -> (epic, _) { epic.end_date.present? } do |epic|
-    epic.end_date&.to_s(:medium)
+    epic.end_date&.to_fs(:medium)
   end
   expose :human_readable_timestamp, if: -> (epic, _) { epic.end_date.present? || epic.start_date.present? } do |epic|
     remaining_days_in_words(epic.end_date, epic.start_date)
diff --git a/ee/app/services/groups/memberships/export_service.rb b/ee/app/services/groups/memberships/export_service.rb
index f77c9c4d707b140543b4d4b2c0d82e6b3b39229e..52a9b6e58e5237a0dffb0e4d1459062fffb2ff1f 100644
--- a/ee/app/services/groups/memberships/export_service.rb
+++ b/ee/app/services/groups/memberships/export_service.rb
@@ -23,7 +23,7 @@ def header_to_value_hash
         {
           'Username' => -> (member) { member&.user&.username },
           'Name' => -> (member) { member&.user&.name },
-          'Access granted' => -> (member) { member.created_at.to_s(:csv) },
+          'Access granted' => -> (member) { member.created_at.to_fs(:csv) },
           'Access expires' => -> (member) { member.expires_at },
           'Max role' => 'human_access',
           'Source' => -> (member) { member_source(member) }
diff --git a/ee/app/services/historical_user_data/csv_service.rb b/ee/app/services/historical_user_data/csv_service.rb
index 9c2d0d64e5df4fa89a5815541f772fc7da4c8af5..1337a634a2c557f7357dd880e582640e74245554 100644
--- a/ee/app/services/historical_user_data/csv_service.rb
+++ b/ee/app/services/historical_user_data/csv_service.rb
@@ -22,7 +22,7 @@ def csv_builder
 
     def header_to_value_hash
       {
-        'Date' => -> (historical_datum) { historical_datum.recorded_at.utc.to_s(:csv) },
+        'Date' => -> (historical_datum) { historical_datum.recorded_at.utc.to_fs(:csv) },
         'Billable User Count' => 'active_user_count'
       }
     end
@@ -35,10 +35,10 @@ def header_csv
       CSV.generate do |csv|
         csv << ['License Key', license.normalized_data]
         csv << ['Email', license.licensee_email]
-        csv << ['License Start Date', license.starts_at&.to_s(:csv)]
-        csv << ['License End Date', license.expires_at&.to_s(:csv)]
+        csv << ['License Start Date', license.starts_at&.to_fs(:csv)]
+        csv << ['License End Date', license.expires_at&.to_fs(:csv)]
         csv << ['Company', license.licensee_company]
-        csv << ['Generated At', Time.current.utc.to_s(:csv)]
+        csv << ['Generated At', Time.current.utc.to_fs(:csv)]
         csv << ['', '']
       end
     end
diff --git a/ee/app/views/admin/users/_credit_card_info.html.haml b/ee/app/views/admin/users/_credit_card_info.html.haml
index 6c0c4eeaa77392ac0ecde27a30536c3c27965cf2..e5239672341befbee43e6c3b566ab93c30403160 100644
--- a/ee/app/views/admin/users/_credit_card_info.html.haml
+++ b/ee/app/views/admin/users/_credit_card_info.html.haml
@@ -16,7 +16,7 @@
         - else
           %span.light= _('Validated at:')
           %strong
-            = credit_card_validation.credit_card_validated_at.to_s(:medium)
+            = credit_card_validation.credit_card_validated_at.to_fs(:medium)
 
       - if credit_card_validation&.holder_name
         %li
diff --git a/ee/app/views/admin/users/card_match.html.haml b/ee/app/views/admin/users/card_match.html.haml
index a21f77fc8518977a07bb9a117353369b454317fe..11430af05ef24c97dffcd53fc17aef319e92698f 100644
--- a/ee/app/views/admin/users/card_match.html.haml
+++ b/ee/app/views/admin/users/card_match.html.haml
@@ -36,10 +36,10 @@
             %td
               = credit_card_validation.holder_name
             %td.gl-text-right
-              = validated_at.to_s(:medium)
+              = validated_at.to_fs(:medium)
               \/
               = validated_at.in_time_zone(stripe_time_zone).strftime(stripe_time_format)
-            %td.gl-text-right= user.created_at.to_s(:medium)
+            %td.gl-text-right= user.created_at.to_fs(:medium)
             %td.gl-text-right
               - if user.current_sign_in_ip
                 = user.current_sign_in_ip
diff --git a/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.html.haml b/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.html.haml
index e215844a0ee6124147a6543c0201f69716952f59..16d9e763e98be6528814b8dc430ef5ca26c221e9 100644
--- a/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.html.haml
+++ b/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.html.haml
@@ -5,7 +5,7 @@
   %li
     = @token.name
   %li
-    = _("Created on %{created_at}") % { created_at: @token.created_at.to_date.to_s(:medium) }
+    = _("Created on %{created_at}") % { created_at: @token.created_at.to_date.to_fs(:medium) }
   - if @token.last_used_at
     %li
       = _("Last used %{last_used_at} ago") % { last_used_at: time_ago_in_words(@token.last_used_at) }
diff --git a/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.text.haml b/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.text.haml
index 4311ec85ec6ae28acbf8d0a90e7bb44624104f16..84b72f1415a6463fdc78b195e2536abb284a411b 100644
--- a/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.text.haml
+++ b/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.text.haml
@@ -2,7 +2,7 @@
 
 = @token.name
 
-= _("Created on %{created_at}") % { created_at: @token.created_at.to_date.to_s(:medium) }
+= _("Created on %{created_at}") % { created_at: @token.created_at.to_date.to_fs(:medium) }
 
 - if @token.last_used_at
   = _("Last used %{last_used_at} ago") % { last_used_at: time_ago_in_words(@token.last_used_at) }
diff --git a/ee/app/views/credentials_inventory_mailer/ssh_key_deleted_email.html.haml b/ee/app/views/credentials_inventory_mailer/ssh_key_deleted_email.html.haml
index 0f149fa20fbaecca54675023b8261990c3b7ceef..0ab2935455bd198d4d33b929b72913d8661db28f 100644
--- a/ee/app/views/credentials_inventory_mailer/ssh_key_deleted_email.html.haml
+++ b/ee/app/views/credentials_inventory_mailer/ssh_key_deleted_email.html.haml
@@ -5,7 +5,7 @@
   %li
     = @params[:title]
   %li
-    = _("Created on %{created_at}") % { created_at: @params[:created_at].to_date.to_s(:medium) }
+    = _("Created on %{created_at}") % { created_at: @params[:created_at].to_date.to_fs(:medium) }
   - if @params[:last_used_at]
     %li
       = _("Last used %{last_used_at} ago") % { last_used_at: time_ago_in_words(@params[:last_used_at]) }
diff --git a/ee/app/views/credentials_inventory_mailer/ssh_key_deleted_email.text.haml b/ee/app/views/credentials_inventory_mailer/ssh_key_deleted_email.text.haml
index 1b31d4e3b043222cdd8a5c3e3426ebb623ec8f94..13bab44b668b6b403edc6b19f0cd40d72952615c 100644
--- a/ee/app/views/credentials_inventory_mailer/ssh_key_deleted_email.text.haml
+++ b/ee/app/views/credentials_inventory_mailer/ssh_key_deleted_email.text.haml
@@ -2,7 +2,7 @@
 
 = @params[:title]
 
-= _("Created on %{created_at}") % { created_at: @params[:created_at].to_date.to_s(:medium) }
+= _("Created on %{created_at}") % { created_at: @params[:created_at].to_date.to_fs(:medium) }
 
 - if @params[:last_used_at]
   = _("Last used %{last_used_at} ago") % { last_used_at: time_ago_in_words(@params[:last_used_at]) }
diff --git a/ee/app/views/shared/billings/_eoa_bronze_plan_banner.html.haml b/ee/app/views/shared/billings/_eoa_bronze_plan_banner.html.haml
index cef0787e71ebff89f69af4237f0337f566a9b88e..ecf01286d992c509be3045d738dbf5799369c54a 100644
--- a/ee/app/views/shared/billings/_eoa_bronze_plan_banner.html.haml
+++ b/ee/app/views/shared/billings/_eoa_bronze_plan_banner.html.haml
@@ -6,4 +6,4 @@
                                dismiss_endpoint: callouts_path }}) do |c|
       - c.with_body do
         - announcement_link = external_link("announcement blog", "https://about.gitlab.com/blog/2021/01/26/new-gitlab-product-subscription-model")
-        = s_("BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}.").html_safe % { announcement_link: announcement_link, eoa_bronze_plan_end_date: eoa_bronze_plan_end_date.in_time_zone.to_date.to_s(:medium) }
+        = s_("BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}.").html_safe % { announcement_link: announcement_link, eoa_bronze_plan_end_date: eoa_bronze_plan_end_date.in_time_zone.to_date.to_fs(:medium) }
diff --git a/ee/lib/gitlab/usage/metrics/instrumentations/count_secure_pipelines_metric.rb b/ee/lib/gitlab/usage/metrics/instrumentations/count_secure_pipelines_metric.rb
index 4f9ac7d2c738a4cf78f7e7a7bd0abbad6a2a89c1..d59e2cd23d71b567eb0792b9db794c44b7897459 100644
--- a/ee/lib/gitlab/usage/metrics/instrumentations/count_secure_pipelines_metric.rb
+++ b/ee/lib/gitlab/usage/metrics/instrumentations/count_secure_pipelines_metric.rb
@@ -80,8 +80,8 @@ def inner_relation
           def outer_relation
             ::Security::Scan
               .from("generate_series(
-                                '#{time_constraints.values[0].first.to_time.to_s(:db)}'::timestamp,
-                                '#{time_constraints.values[0].last.to_time.to_s(:db)}'::timestamp,
+                                '#{time_constraints.values[0].first.to_time.to_fs(:db)}'::timestamp,
+                                '#{time_constraints.values[0].last.to_time.to_fs(:db)}'::timestamp,
                                 '1 day'::interval) date_range_source")
           end
 
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_ci_builds_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_ci_builds_metric_spec.rb
index 00404d5a03bc7e240ceb4853d177d4739ceae3a0..608582e36df9c3275adbc7dcf61567b7ec6709fa 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_ci_builds_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_ci_builds_metric_spec.rb
@@ -99,8 +99,8 @@
   end
 
   context 'with time_frame 28d' do
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
     let(:expected_query) { "SELECT COUNT(\"#{builds_table_name}\".\"id\") FROM \"#{builds_table_name}\" WHERE \"#{builds_table_name}\".\"type\" = 'Ci::Build' AND \"#{builds_table_name}\".\"created_at\" BETWEEN '#{start}' AND '#{finish}' AND \"#{builds_table_name}\".\"name\" = '#{secure_type}'" }
 
     it_behaves_like 'a correct secure type instrumented metric value', { time_frame: '28d', expected_value: 1 }
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_ci_environments_approval_required_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_ci_environments_approval_required_spec.rb
index 05827d8f48c627b00dbf9a9d3dee3ea0f6d10dac..17686365bfd05e821a5c8cb9b05b0c4078de3aa6 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_ci_environments_approval_required_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_ci_environments_approval_required_spec.rb
@@ -42,8 +42,8 @@
       create_list(:protected_environment_approval_rule, 2, :maintainer_access, created_at: 3.days.ago)
     end
 
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
 
     let(:expected_value) { 2 }
     let(:expected_query) do
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_deployment_approvals_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_deployment_approvals_metric_spec.rb
index e81a22bf30f6604504f16cb9879bb35398b67cd1..347af12c8dbf1ccda3ccf9b10c036e354a3f10d6 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_deployment_approvals_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_deployment_approvals_metric_spec.rb
@@ -16,8 +16,8 @@
     let_it_be(:old_deployment_approval) { create(:deployment_approval, created_at: 30.days.ago) }
     let_it_be(:deployment_approvals) { create_list(:deployment_approval, 2, created_at: 2.days.ago) }
 
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
 
     let(:expected_value) { 2 }
     let(:expected_query) do
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_groups_with_assigned_security_policy_project_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_groups_with_assigned_security_policy_project_metric_spec.rb
index 3ed55f7a83cfbb77ced5a48458b19dbf3f765eb3..87d911ef762b9facdd01107bb91696c7a4e4b42e 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_groups_with_assigned_security_policy_project_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_groups_with_assigned_security_policy_project_metric_spec.rb
@@ -21,8 +21,8 @@
 
   it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d', data_source: 'database' } do
     let(:expected_value) { 1 }
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
     let(:expected_query) do
       "SELECT COUNT(DISTINCT \"security_orchestration_policy_configurations\".\"namespace_id\") " \
         "FROM \"security_orchestration_policy_configurations\" " \
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_merge_requests_with_applied_scan_result_policies_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_merge_requests_with_applied_scan_result_policies_metric_spec.rb
index ea895f0a348998921ab8480722df6706d69937ca..1ae1c77d57613ca4994d85ac19e60453a4115cb6 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_merge_requests_with_applied_scan_result_policies_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_merge_requests_with_applied_scan_result_policies_metric_spec.rb
@@ -23,8 +23,8 @@
 
   it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d', data_source: 'database' } do
     let(:expected_value) { 1 }
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
     let(:expected_query) do
       "SELECT COUNT(DISTINCT \"approval_merge_request_rules\".\"merge_request_id\") " \
         "FROM \"approval_merge_request_rules\" WHERE \"approval_merge_request_rules\".\"report_type\" = 4 " \
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_projects_with_applied_scan_result_policies_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_projects_with_applied_scan_result_policies_metric_spec.rb
index 31babb246bf0835b8682bd56ad003a7ba6fcf064..5c2e296331ca5cbf84d9848537ff71a1b7fcf0d8 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_projects_with_applied_scan_result_policies_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_projects_with_applied_scan_result_policies_metric_spec.rb
@@ -25,8 +25,8 @@
 
   it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d', data_source: 'database' } do
     let(:expected_value) { 1 }
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
     let(:expected_query) do
       "SELECT COUNT(DISTINCT \"approval_project_rules\".\"project_id\") FROM \"approval_project_rules\" " \
         "WHERE \"approval_project_rules\".\"report_type\" = 4 " \
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_projects_with_assigned_security_policy_project_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_projects_with_assigned_security_policy_project_metric_spec.rb
index d2aade60216e65fc8c8637a7dbd093fcad21339d..01c5649e82da332957303820ba6db54905d3a2b3 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_projects_with_assigned_security_policy_project_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_projects_with_assigned_security_policy_project_metric_spec.rb
@@ -21,8 +21,8 @@
 
   it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d', data_source: 'database' } do
     let(:expected_value) { 1 }
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
     let(:expected_query) do
       "SELECT COUNT(DISTINCT \"security_orchestration_policy_configurations\".\"project_id\") " \
         "FROM \"security_orchestration_policy_configurations\" " \
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_secure_pipelines_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_secure_pipelines_metric_spec.rb
index cda69c558e0d6098f4b450e1f4e0a02bb9a49614..60a1cb70080d0b0afc9a5b56cfbb537d43a56223 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_secure_pipelines_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_secure_pipelines_metric_spec.rb
@@ -109,8 +109,8 @@
 
   ::Security::Scan.scan_types.except('cluster_image_scanning').each do |name, scan_type|
     context "with scan_type #{name}" do
-      let(:start) { 30.days.ago.to_s(:db) }
-      let(:finish) { 2.days.ago.to_s(:db) }
+      let(:start) { 30.days.ago.to_fs(:db) }
+      let(:finish) { 2.days.ago.to_fs(:db) }
       let(:expected_query) do
         %{SELECT COUNT(DISTINCT "security_scans"."pipeline_id") FROM "security_scans" WHERE "security_scans"."created_at" BETWEEN '#{start}' AND '#{finish}' AND "security_scans"."scan_type" = #{scan_type}} # rubocop:disable Layout/LineLength
       end
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_security_scans_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_security_scans_metric_spec.rb
index 6f19a56ef739da63ce8112085cf538d1a9574aff..2d453af1afaaea20182295045250c5cfd016ca48 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_security_scans_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_security_scans_metric_spec.rb
@@ -36,8 +36,8 @@
   end
 
   context 'with time_frame 28d' do
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
 
     it_behaves_like 'a correct secure type instrumented metric value', { time_frame: '28d', expected_value: 1 }
   end
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_user_merge_requests_for_projects_with_applied_scan_result_policies_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_user_merge_requests_for_projects_with_applied_scan_result_policies_metric_spec.rb
index 9ba5c341fa0516146c3e9de247d8e87622a12896..026b73061ea2464e8604baf2d26469f848d36590 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_user_merge_requests_for_projects_with_applied_scan_result_policies_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_user_merge_requests_for_projects_with_applied_scan_result_policies_metric_spec.rb
@@ -60,8 +60,8 @@
 
   it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d', data_source: 'database' } do
     let(:expected_value) { 1 }
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
     let(:expected_query) do
       "SELECT COUNT(DISTINCT \"merge_requests\".\"author_id\") FROM \"merge_requests\" " \
         "INNER JOIN security_orchestration_policy_configurations " \
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_user_merge_requests_with_applied_scan_result_policies_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_user_merge_requests_with_applied_scan_result_policies_metric_spec.rb
index 4d17e844cd91ea892a53ff3cb5f411b3e5b58c56..e91402aabbbf3e92cc6c50e27c8b4458185af5f2 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_user_merge_requests_with_applied_scan_result_policies_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_user_merge_requests_with_applied_scan_result_policies_metric_spec.rb
@@ -46,8 +46,8 @@
 
   it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d', data_source: 'database' } do
     let(:expected_value) { 1 }
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
     let(:expected_query) do
       "SELECT COUNT(DISTINCT \"merge_requests\".\"author_id\") FROM \"merge_requests\" " \
         "INNER JOIN \"approval_merge_request_rules\" " \
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_ci_builds_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_ci_builds_metric_spec.rb
index 61f9d76950b9f4a469a72c7a8cf238a36ef14fbe..22f14db4f328088efbc0b81c0810ca553ef0f7b4 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_ci_builds_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_ci_builds_metric_spec.rb
@@ -113,8 +113,8 @@
   end
 
   context 'with time_frame 28d' do
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
     let(:expected_query) { "SELECT COUNT(DISTINCT \"#{builds_table_name}\".\"user_id\") FROM \"#{builds_table_name}\" WHERE \"#{builds_table_name}\".\"type\" = 'Ci::Build' AND \"#{builds_table_name}\".\"created_at\" BETWEEN '#{start}' AND '#{finish}' AND \"#{builds_table_name}\".\"name\" = '#{secure_type}'" }
 
     it_behaves_like 'a correct secure type instrumented metric value', { time_frame: '28d', expected_value: 1 }
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/protected_environment_approval_rules_required_approvals_average_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/protected_environment_approval_rules_required_approvals_average_metric_spec.rb
index 7d2e9dae34778a15c9c1eb41edba297748b5aee2..d5cc00e461a708161c5a53fd20872c15273436ab 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/protected_environment_approval_rules_required_approvals_average_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/protected_environment_approval_rules_required_approvals_average_metric_spec.rb
@@ -9,8 +9,8 @@
   let_it_be(:rule_for_developer_within_timeframe) { create(:protected_environment_approval_rule, :developer_access, required_approvals: 1, created_at: 3.days.ago) }
   # rubocop:enable Layout/LineLength
 
-  let(:start) { 30.days.ago.to_s(:db) }
-  let(:finish) { 2.days.ago.to_s(:db) }
+  let(:start) { 30.days.ago.to_fs(:db) }
+  let(:finish) { 2.days.ago.to_fs(:db) }
 
   let(:expected_value) { 1.5 }
   let(:expected_query) do
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/protected_environments_required_approvals_average_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/protected_environments_required_approvals_average_metric_spec.rb
index 81ecf2708d63fbf5601120bfcfc1e87b02592b1b..436f6601d3dd2b48b6da6ab97115ca9cbbe56f5e 100644
--- a/ee/spec/lib/gitlab/usage/metrics/instrumentations/protected_environments_required_approvals_average_metric_spec.rb
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/protected_environments_required_approvals_average_metric_spec.rb
@@ -11,8 +11,8 @@
     create(:protected_environment, :staging, required_approval_count: 1, created_at: 3.days.ago)
   end
 
-  let(:start) { 30.days.ago.to_s(:db) }
-  let(:finish) { 2.days.ago.to_s(:db) }
+  let(:start) { 30.days.ago.to_fs(:db) }
+  let(:finish) { 2.days.ago.to_fs(:db) }
 
   let(:expected_value) { 1.5 }
   let(:expected_query) do
diff --git a/ee/spec/mailers/credentials_inventory_mailer_spec.rb b/ee/spec/mailers/credentials_inventory_mailer_spec.rb
index 7c89935b9e23c0f64f5a4f48d6cc5a6aabf0f90a..a288a9ce0ab5444523c0eeaadae0162000dcbd85 100644
--- a/ee/spec/mailers/credentials_inventory_mailer_spec.rb
+++ b/ee/spec/mailers/credentials_inventory_mailer_spec.rb
@@ -15,7 +15,7 @@
     it { is_expected.to have_subject 'Your Personal Access Token was revoked' }
     it { is_expected.to have_body_text 'The following Personal Access Token was revoked by an administrator, Revoker' }
     it { is_expected.to have_body_text token.name }
-    it { is_expected.to have_body_text "Created on #{token.created_at.to_date.to_s(:medium)}" }
+    it { is_expected.to have_body_text "Created on #{token.created_at.to_date.to_fs(:medium)}" }
     it { is_expected.to have_body_text 'Scopes: api, sudo' }
     it { is_expected.to be_delivered_to [token.user.notification_email_or_default] }
     it { is_expected.to have_body_text 'Last used 21 days ago' }
@@ -39,7 +39,7 @@
     it { is_expected.to have_body_text 'The following SSH key was deleted by an administrator, Revoker' }
     it { is_expected.to be_delivered_to [ssh_key.user.notification_email_or_default] }
     it { is_expected.to have_body_text ssh_key.title }
-    it { is_expected.to have_body_text "Created on #{ssh_key.created_at.to_date.to_s(:medium)}" }
+    it { is_expected.to have_body_text "Created on #{ssh_key.created_at.to_date.to_fs(:medium)}" }
     it { is_expected.to have_body_text 'Last used 21 days ago' }
   end
 end
diff --git a/ee/spec/services/analytics/cycle_analytics/consistency_check_service_spec.rb b/ee/spec/services/analytics/cycle_analytics/consistency_check_service_spec.rb
index d3c852a4568f141465d1d3215c40d70df9206192..c7418731d518c94b6663548de07050531dfadbf8 100644
--- a/ee/spec/services/analytics/cycle_analytics/consistency_check_service_spec.rb
+++ b/ee/spec/services/analytics/cycle_analytics/consistency_check_service_spec.rb
@@ -63,8 +63,8 @@
             last_processed_event = initial_events[i]
 
             expect(response.payload[:cursor]).to eq({
-              'start_event_timestamp' => last_processed_event.start_event_timestamp.to_s(:inspect),
-              'end_event_timestamp' => last_processed_event.end_event_timestamp&.to_s(:inspect),
+              'start_event_timestamp' => last_processed_event.start_event_timestamp.to_fs(:inspect),
+              'end_event_timestamp' => last_processed_event.end_event_timestamp&.to_fs(:inspect),
               event_model.issuable_id_column.to_s => last_processed_event[event_model.issuable_id_column].to_s
             })
 
diff --git a/ee/spec/services/historical_user_data/csv_service_spec.rb b/ee/spec/services/historical_user_data/csv_service_spec.rb
index f6031507b65360f8d20bef3aaf0617306b0fc4f2..c778dc66ff6386ceb69d7b7d93a30d4c1925f29b 100644
--- a/ee/spec/services/historical_user_data/csv_service_spec.rb
+++ b/ee/spec/services/historical_user_data/csv_service_spec.rb
@@ -57,7 +57,7 @@
       end
 
       it 'shows the license start date' do
-        expect(csv[2][1]).to eq(license_start_date.to_s(:csv))
+        expect(csv[2][1]).to eq(license_start_date.to_fs(:csv))
       end
     end
 
@@ -67,7 +67,7 @@
       end
 
       it 'shows the license end date' do
-        expect(csv[3][1]).to eq(license_end_date.to_s(:csv))
+        expect(csv[3][1]).to eq(license_end_date.to_fs(:csv))
       end
     end
 
@@ -87,7 +87,7 @@
       end
 
       it 'shows the CSV generation time' do
-        expect(csv[5][1]).to eq(datetime.utc.to_s(:csv))
+        expect(csv[5][1]).to eq(datetime.utc.to_fs(:csv))
       end
     end
   end
@@ -114,11 +114,11 @@
 
     it 'includes proper values for each column type', :aggregate_failures do
       expect(csv[8]).to contain_exactly(
-        historical_datum.recorded_at.utc.to_s(:csv),
+        historical_datum.recorded_at.utc.to_fs(:csv),
         historical_datum.active_user_count.to_s
       )
       expect(csv[9]).to contain_exactly(
-        historical_datum2.recorded_at.utc.to_s(:csv),
+        historical_datum2.recorded_at.utc.to_fs(:csv),
         historical_datum2.active_user_count.to_s
       )
     end
diff --git a/ee/spec/workers/gitlab_subscriptions/refresh_seats_worker_spec.rb b/ee/spec/workers/gitlab_subscriptions/refresh_seats_worker_spec.rb
index c0489a696430c194f0ee128db4be4f4f9b64c30a..c1e93ab9a84c45fc2a1b0e739fbd4ce76dcff829 100644
--- a/ee/spec/workers/gitlab_subscriptions/refresh_seats_worker_spec.rb
+++ b/ee/spec/workers/gitlab_subscriptions/refresh_seats_worker_spec.rb
@@ -107,7 +107,7 @@
           namespace: create(:namespace, :with_namespace_settings),
           seats: 11,
           max_seats_used: 11,
-          last_seat_refresh_at: 1.hour.ago.to_s(:db)
+          last_seat_refresh_at: 1.hour.ago.to_fs(:db)
         )
       end
 
diff --git a/lib/gitlab/pagination/keyset/order.rb b/lib/gitlab/pagination/keyset/order.rb
index 0d8e4ea6fee2cc3c6db518cd9e6a01b9f3e47778..e31e83c90daebdfa586ad393a581d41cce978f1d 100644
--- a/lib/gitlab/pagination/keyset/order.rb
+++ b/lib/gitlab/pagination/keyset/order.rb
@@ -98,7 +98,7 @@ def cursor_attributes_for_node(node)
             hash[column_definition.attribute_name] = if field_value.is_a?(Time)
                                                        # use :inspect formatter to provide specific timezone info
                                                        # eg 2022-07-05 21:57:56.041499000 +0800
-                                                       field_value.to_s(:inspect)
+                                                       field_value.to_fs(:inspect)
                                                      elsif field_value.nil?
                                                        nil
                                                      elsif lower_named_function?(column_definition)
diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb
index fe4b80e12feadbcdf1fa75e110c18408f8af9284..feebdd972aa7f07aa5011832108c4bc1d77c2c24 100644
--- a/spec/controllers/groups/group_members_controller_spec.rb
+++ b/spec/controllers/groups/group_members_controller_spec.rb
@@ -234,7 +234,7 @@
         it 'returns correct json response' do
           expect(json_response).to eq({
             "expires_soon" => false,
-            "expires_at_formatted" => expiry_date.to_time.in_time_zone.to_s(:medium)
+            "expires_at_formatted" => expiry_date.to_time.in_time_zone.to_fs(:medium)
           })
         end
       end
diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb
index ad49529b4262ae8affd297594155f19660ca0a55..9657cf33afd871861fc823ae2494cd76763c973a 100644
--- a/spec/controllers/projects/project_members_controller_spec.rb
+++ b/spec/controllers/projects/project_members_controller_spec.rb
@@ -320,7 +320,7 @@
           it 'returns correct json response' do
             expect(json_response).to eq({
               "expires_soon" => false,
-              "expires_at_formatted" => expiry_date.to_time.in_time_zone.to_s(:medium)
+              "expires_at_formatted" => expiry_date.to_time.in_time_zone.to_fs(:medium)
             })
           end
         end
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index d4148717f0a64af655e9e4fadeeac4bab5d84c5f..57183b2e8d91d4426487113935675d4c850da363 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -159,7 +159,7 @@
         click_button 'Create issue'
 
         page.within '.issuable-sidebar' do
-          expect(page).to have_content date.to_s(:medium)
+          expect(page).to have_content date.to_fs(:medium)
         end
       end
     end
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index 7e54580b0851b26775fce4aae658236461439569..47c532c396313d0f33be88dafc7767d455d83459 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -82,7 +82,7 @@
           click_button _('Save changes')
 
           page.within '.issuable-sidebar' do
-            expect(page).to have_content date.to_s(:medium)
+            expect(page).to have_content date.to_fs(:medium)
           end
         end
 
diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
index 44660b247a163cac3bc331f38bd95cd95e19c1cd..d237faba66381633f80e7fe0b66b1d22a6ce52ec 100644
--- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
@@ -39,7 +39,7 @@ def assert_env_widget(text, env_name)
         wait_for_requests
 
         assert_env_widget("Deployed to", environment.name)
-        expect(find('.js-deploy-time')['title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium))
+        expect(find('.js-deploy-time')['title']).to eq(deployment.created_at.to_time.in_time_zone.to_fs(:medium))
       end
 
       context 'when a user created a new merge request with the same SHA' do
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index ffaffa251d1f3ef164094d5900743facb851e4e7..a2b8ee061bb31ffcc24df2cfdb97c93f745800c5 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -666,9 +666,11 @@
 
   describe '#sidebar_milestone_tooltip_label' do
     it 'escapes HTML in the milestone title' do
-      milestone = build(:milestone, title: '&lt;img onerror=alert(1)&gt;')
+      milestone = build(:milestone, title: '&lt;img onerror=alert(1)&gt;', due_date: Date.new(2022, 6, 26))
 
-      expect(helper.sidebar_milestone_tooltip_label(milestone)).to eq('&lt;img onerror=alert(1)&gt;<br/>Milestone')
+      expect(helper.sidebar_milestone_tooltip_label(milestone)).to eq(
+        '&lt;img onerror=alert(1)&gt;<br/>Jun 26, 2022 (<strong>Past due</strong>)'
+      )
     end
   end
 
diff --git a/spec/helpers/page_layout_helper_spec.rb b/spec/helpers/page_layout_helper_spec.rb
index b14789fd5d2354d4e84dbda9e830b695b1915f64..43500d985917fdba230891dc4611d024ffe6c169 100644
--- a/spec/helpers/page_layout_helper_spec.rb
+++ b/spec/helpers/page_layout_helper_spec.rb
@@ -270,7 +270,7 @@
 
       it 'merges the status properties with the defaults' do
         is_expected.to eq({
-          current_clear_status_after: time.to_s(:iso8601),
+          current_clear_status_after: time.to_fs(:iso8601),
           current_availability: 'busy',
           current_emoji: 'basketball',
           current_message: 'Some message',
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
index 773df9b20eeff40f0ac5df8b2fb56b5801b9a720..56fef37f93996f533da051115c7d64e97fb16e37 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
@@ -104,7 +104,7 @@ def decoded_cursor(cursor)
         let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_updated_at, column_order_created_at, column_order_id])) }
 
         it 'returns the encoded value of the order' do
-          expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s(:inspect))
+          expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_fs(:inspect))
         end
       end
     end
diff --git a/spec/lib/gitlab/pagination/keyset/iterator_spec.rb b/spec/lib/gitlab/pagination/keyset/iterator_spec.rb
index eee743c5e48c11621798305719e6d6808a48cd35..afaad48d363e8e308c87fe82d0d5ff9971d6d822 100644
--- a/spec/lib/gitlab/pagination/keyset/iterator_spec.rb
+++ b/spec/lib/gitlab/pagination/keyset/iterator_spec.rb
@@ -87,7 +87,7 @@
         time = Time.current
 
         iterator.each_batch(of: 2) do |relation|
-          Issue.connection.execute("UPDATE issues SET updated_at = '#{time.to_s(:inspect)}' WHERE id IN (#{relation.reselect(:id).to_sql})")
+          Issue.connection.execute("UPDATE issues SET updated_at = '#{time.to_fs(:inspect)}' WHERE id IN (#{relation.reselect(:id).to_sql})")
         end
 
         expect(Issue.pluck(:updated_at)).to all(be_within(5.seconds).of(time))
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric_spec.rb
index 317929f77e685eb35dab0e5ab4feaef7352b7daa..eee5396bdbf520ef58814af4324619746d819350 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric_spec.rb
@@ -30,8 +30,8 @@
 
     context 'for 28d time frame' do
       let(:expected_value) { 6 }
-      let(:start) { 30.days.ago.to_s(:db) }
-      let(:finish) { 2.days.ago.to_s(:db) }
+      let(:start) { 30.days.ago.to_fs(:db) }
+      let(:finish) { 2.days.ago.to_fs(:db) }
       let(:expected_query) do
         "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\""\
         " WHERE \"bulk_import_entities\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'"
@@ -63,8 +63,8 @@
 
     context 'for 28d time frame' do
       let(:expected_value) { 3 }
-      let(:start) { 30.days.ago.to_s(:db) }
-      let(:finish) { 2.days.ago.to_s(:db) }
+      let(:start) { 30.days.ago.to_fs(:db) }
+      let(:finish) { 2.days.ago.to_fs(:db) }
       let(:expected_query) do
         "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\""\
         " WHERE \"bulk_import_entities\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'"\
@@ -92,8 +92,8 @@
 
     context 'for 28d time frame' do
       let(:expected_value) { 3 }
-      let(:start) { 30.days.ago.to_s(:db) }
-      let(:finish) { 2.days.ago.to_s(:db) }
+      let(:start) { 30.days.ago.to_fs(:db) }
+      let(:finish) { 2.days.ago.to_fs(:db) }
       let(:expected_query) do
         "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\""\
         " WHERE \"bulk_import_entities\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'"\
@@ -121,8 +121,8 @@
 
     context 'for 28d time frame' do
       let(:expected_value) { 4 }
-      let(:start) { 30.days.ago.to_s(:db) }
-      let(:finish) { 2.days.ago.to_s(:db) }
+      let(:start) { 30.days.ago.to_fs(:db) }
+      let(:finish) { 2.days.ago.to_fs(:db) }
       let(:expected_query) do
         "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\""\
         " WHERE \"bulk_import_entities\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'"\
@@ -150,8 +150,8 @@
 
     context 'for 28d time frame' do
       let(:expected_value) { 2 }
-      let(:start) { 30.days.ago.to_s(:db) }
-      let(:finish) { 2.days.ago.to_s(:db) }
+      let(:start) { 30.days.ago.to_fs(:db) }
+      let(:finish) { 2.days.ago.to_fs(:db) }
       let(:expected_query) do
         "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\""\
         " WHERE \"bulk_import_entities\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'"\
@@ -202,8 +202,8 @@
 
     context 'for 28d time frame' do
       let(:expected_value) { 3 }
-      let(:start) { 30.days.ago.to_s(:db) }
-      let(:finish) { 2.days.ago.to_s(:db) }
+      let(:start) { 30.days.ago.to_fs(:db) }
+      let(:finish) { 2.days.ago.to_fs(:db) }
       let(:expected_query) do
         "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\" " \
           "WHERE \"bulk_import_entities\".\"created_at\" BETWEEN '#{start}' AND '#{finish}' " \
@@ -249,8 +249,8 @@
     context 'for 28d time frame' do
       context 'with project entity' do
         let(:expected_value) { 2 }
-        let(:start) { 30.days.ago.to_s(:db) }
-        let(:finish) { 2.days.ago.to_s(:db) }
+        let(:start) { 30.days.ago.to_fs(:db) }
+        let(:finish) { 2.days.ago.to_fs(:db) }
         let(:expected_query) do
           "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\" " \
             "WHERE \"bulk_import_entities\".\"created_at\" BETWEEN '#{start}' AND '#{finish}' " \
@@ -265,8 +265,8 @@
 
       context 'with group entity' do
         let(:expected_value) { 2 }
-        let(:start) { 30.days.ago.to_s(:db) }
-        let(:finish) { 2.days.ago.to_s(:db) }
+        let(:start) { 30.days.ago.to_fs(:db) }
+        let(:finish) { 2.days.ago.to_fs(:db) }
         let(:expected_query) do
           "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\" " \
             "WHERE \"bulk_import_entities\".\"created_at\" BETWEEN '#{start}' AND '#{finish}' " \
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric_spec.rb
index b7da9b27e1943b4ebeb53ee6199c43a106c0cb0a..8ae64e8db2346c92f9e4b02010c60b581def9d39 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric_spec.rb
@@ -43,8 +43,8 @@
 
     context 'for 28d time frame' do
       let(:expected_value) { 3 }
-      let(:start) { 30.days.ago.to_s(:db) }
-      let(:finish) { 2.days.ago.to_s(:db) }
+      let(:start) { 30.days.ago.to_fs(:db) }
+      let(:finish) { 2.days.ago.to_fs(:db) }
       let(:expected_query) do
         "SELECT COUNT(\"projects\".\"id\") FROM \"projects\" WHERE \"projects\".\"created_at\""\
         " BETWEEN '#{start}' AND '#{finish}' AND \"projects\".\"import_type\" = 'gitea'"
@@ -70,8 +70,8 @@
 
     context 'for 28d time frame' do
       let(:expected_value) { 2 }
-      let(:start) { 30.days.ago.to_s(:db) }
-      let(:finish) { 2.days.ago.to_s(:db) }
+      let(:start) { 30.days.ago.to_fs(:db) }
+      let(:finish) { 2.days.ago.to_fs(:db) }
       let(:expected_query) do
         "SELECT COUNT(\"projects\".\"id\") FROM \"projects\" WHERE \"projects\".\"created_at\""\
         " BETWEEN '#{start}' AND '#{finish}' AND \"projects\".\"import_type\" = 'bitbucket'"
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric_spec.rb
index bfc4240def69d8e52497c13ca9fa1c63bf4dd55a..bd432b614e7e83d5c347290bc065276f25bbd118 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric_spec.rb
@@ -45,8 +45,8 @@
 
   context 'for 28d time frame' do
     let(:expected_value) { 8 }
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
     let(:expected_query) do
       "SELECT (SELECT COUNT(\"projects\".\"id\") FROM \"projects\" WHERE \"projects\".\"import_type\""\
       " IN ('gitlab_project', 'gitlab', 'github', 'bitbucket', 'bitbucket_server', 'gitea', 'git', 'manifest',"\
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb
index 3fb4c3a4e3fcb84f082751aa58565a1bcf8a7c01..86aa37b494a2173c8a5c3bf95bbc4f9cd1cf2593 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb
@@ -16,8 +16,8 @@
 
   context 'for 28d time frame' do
     let(:expected_value) { 1 }
-    let(:start) { 30.days.ago.to_s(:db) }
-    let(:finish) { 2.days.ago.to_s(:db) }
+    let(:start) { 30.days.ago.to_fs(:db) }
+    let(:finish) { 2.days.ago.to_fs(:db) }
     let(:expected_query) { "SELECT COUNT(DISTINCT \"issues\".\"author_id\") FROM \"issues\" WHERE \"issues\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'" }
 
     it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d' }
diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb
index 46a876f34e9947912de91fe56b9abe655d9d37b3..01efe66a4193c3f9ecdf296f8e93087acd4c05c7 100644
--- a/spec/models/concerns/milestoneish_spec.rb
+++ b/spec/models/concerns/milestoneish_spec.rb
@@ -356,4 +356,20 @@
       expect(milestone.human_total_time_estimate).to be_nil
     end
   end
+
+  describe '#expires_at' do
+    it 'returns the date when milestone expires' do
+      due_date = Date.today + 1.day
+      milestone.due_date = due_date
+
+      expect(milestone.expires_at).to eq("expires on #{due_date.to_fs(:medium)}")
+    end
+
+    it 'returns the date when milestone expires' do
+      due_date = Date.today - 1.day
+      milestone.due_date = due_date
+
+      expect(milestone.expires_at).to eq("expired on #{due_date.to_fs(:medium)}")
+    end
+  end
 end
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index bd09dae0a5a741842d4844ea32bee0810dc44fa4..fd614fba091e56eac042ab38f0d474f63604c860 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -301,7 +301,7 @@
       it 'returns due_date message: Date.new(2016, 8, 28) if content contains /due 2016-08-28' do
         _, _, message = service.execute(content, issuable)
 
-        expect(message).to eq("Set the due date to #{expected_date.to_s(:medium)}.")
+        expect(message).to eq("Set the due date to #{expected_date.to_fs(:medium)}.")
       end
     end
 
diff --git a/spec/services/system_notes/time_tracking_service_spec.rb b/spec/services/system_notes/time_tracking_service_spec.rb
index 71228050085f0e08ed46e2ce190c94bb2ea711f3..a3793880ff17da8b339fffb11815078056c181f2 100644
--- a/spec/services/system_notes/time_tracking_service_spec.rb
+++ b/spec/services/system_notes/time_tracking_service_spec.rb
@@ -25,7 +25,7 @@
 
       context 'when both dates are added' do
         it 'sets the correct note message' do
-          expect(note.note).to eq("changed start date to #{start_date.to_s(:long)} and changed due date to #{due_date.to_s(:long)}")
+          expect(note.note).to eq("changed start date to #{start_date.to_fs(:long)} and changed due date to #{due_date.to_fs(:long)}")
         end
       end
 
@@ -37,7 +37,7 @@
         end
 
         it 'sets the correct note message' do
-          expect(note.note).to eq("removed start date #{start_date.to_s(:long)} and removed due date #{due_date.to_s(:long)}")
+          expect(note.note).to eq("removed start date #{start_date.to_fs(:long)} and removed due date #{due_date.to_fs(:long)}")
         end
       end
 
@@ -45,14 +45,14 @@
         let(:changed_dates) { { 'due_date' => [nil, due_date] } }
 
         it 'sets the correct note message' do
-          expect(note.note).to eq("changed due date to #{due_date.to_s(:long)}")
+          expect(note.note).to eq("changed due date to #{due_date.to_fs(:long)}")
         end
 
         context 'and start date removed' do
           let(:changed_dates) { { 'due_date' => [nil, due_date], 'start_date' => [start_date, nil] } }
 
           it 'sets the correct note message' do
-            expect(note.note).to eq("removed start date #{start_date.to_s(:long)} and changed due date to #{due_date.to_s(:long)}")
+            expect(note.note).to eq("removed start date #{start_date.to_fs(:long)} and changed due date to #{due_date.to_fs(:long)}")
           end
         end
       end
@@ -73,14 +73,14 @@
         end
 
         it 'sets the correct note message' do
-          expect(note.note).to eq("changed start date to #{start_date.to_s(:long)}")
+          expect(note.note).to eq("changed start date to #{start_date.to_fs(:long)}")
         end
 
         context 'and due date removed' do
           let(:changed_dates) { { 'due_date' => [due_date, nil], 'start_date' => [nil, start_date] } }
 
           it 'sets the correct note message' do
-            expect(note.note).to eq("changed start date to #{start_date.to_s(:long)} and removed due date #{due_date.to_s(:long)}")
+            expect(note.note).to eq("changed start date to #{start_date.to_fs(:long)} and removed due date #{due_date.to_fs(:long)}")
           end
         end
       end
diff --git a/spec/services/work_items/export_csv_service_spec.rb b/spec/services/work_items/export_csv_service_spec.rb
index 948ff89245e4c1d10ee13a93e851d26507609df3..4566289231faa9b5de5cee130f2142de8b658f5c 100644
--- a/spec/services/work_items/export_csv_service_spec.rb
+++ b/spec/services/work_items/export_csv_service_spec.rb
@@ -61,7 +61,7 @@ def csv
   end
 
   specify 'created_at' do
-    expect(csv[0]['Created At (UTC)']).to eq(work_item_1.created_at.to_s(:csv))
+    expect(csv[0]['Created At (UTC)']).to eq(work_item_1.created_at.to_fs(:csv))
   end
 
   specify 'description' do
diff --git a/spec/support/helpers/features/iteration_helpers.rb b/spec/support/helpers/features/iteration_helpers.rb
index fab373a547f1018ba9c445ae4c92c00db2cb656a..7ae546fb83c199fbb0c530ccce3824063551c995 100644
--- a/spec/support/helpers/features/iteration_helpers.rb
+++ b/spec/support/helpers/features/iteration_helpers.rb
@@ -3,7 +3,7 @@
 module Features
   module IterationHelpers
     def iteration_period(iteration)
-      "#{iteration.start_date.to_s(:medium)} - #{iteration.due_date.to_s(:medium)}"
+      "#{iteration.start_date.to_fs(:medium)} - #{iteration.due_date.to_fs(:medium)}"
     end
   end
 end
diff --git a/spec/support/shared_examples/features/sidebar/sidebar_due_date_shared_examples.rb b/spec/support/shared_examples/features/sidebar/sidebar_due_date_shared_examples.rb
index 206116d66c8fe7861d1180a777a40e05ff057a05..865f5aff476abdf2f65db667e70919ad45ba3d2e 100644
--- a/spec/support/shared_examples/features/sidebar/sidebar_due_date_shared_examples.rb
+++ b/spec/support/shared_examples/features/sidebar/sidebar_due_date_shared_examples.rb
@@ -26,7 +26,7 @@
 
         wait_for_requests
 
-        expect(page).to have_content(today.to_s(:medium))
+        expect(page).to have_content(today.to_fs(:medium))
         expect(due_date_value.text).to have_content Time.current.strftime('%b %-d, %Y')
       end
     end
diff --git a/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb b/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
index 6f104f400bcc610057033dc4ac56fb0699e615a5..52f0e7847b09027e49985291862d9af93a631c79 100644
--- a/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
+++ b/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
@@ -2,7 +2,7 @@
 
 RSpec.shared_examples 'StageEventModel' do
   describe '.upsert_data' do
-    let(:time) { Time.parse(Time.current.to_s(:db)) } # truncating the timestamp so we can compare it with the timestamp loaded from the DB
+    let(:time) { Time.parse(Time.current.to_fs(:db)) } # truncating the timestamp so we can compare it with the timestamp loaded from the DB
     let(:input_data) do
       [
         {
diff --git a/spec/views/profiles/show.html.haml_spec.rb b/spec/views/profiles/show.html.haml_spec.rb
index ea0a9ebb02cde693be246a0487ad557f72a935f5..e88b1bf40533d2d0cafa7571cb3f7a6776972f1a 100644
--- a/spec/views/profiles/show.html.haml_spec.rb
+++ b/spec/views/profiles/show.html.haml_spec.rb
@@ -46,7 +46,7 @@
       )
       expect(rendered).to have_field(
         'user[status][clear_status_after]',
-        with: user_status.clear_status_at.to_s(:iso8601),
+        with: user_status.clear_status_at.to_fs(:iso8601),
         type: :hidden
       )
     end