diff --git a/models/actions/run.go b/models/actions/run.go
index 1a3701b0b0ae..fcac58d515c3 100644
--- a/models/actions/run.go
+++ b/models/actions/run.go
@@ -46,10 +46,13 @@ type ActionRun struct {
 	TriggerEvent      string                       // the trigger event defined in the `on` configuration of the triggered workflow
 	Status            Status                       `xorm:"index"`
 	Version           int                          `xorm:"version default 0"` // Status could be updated concomitantly, so an optimistic lock is needed
-	Started           timeutil.TimeStamp
-	Stopped           timeutil.TimeStamp
-	Created           timeutil.TimeStamp `xorm:"created"`
-	Updated           timeutil.TimeStamp `xorm:"updated"`
+	// Started and Stopped is used for recording last run time, if rerun happened, they will be reset to 0
+	Started timeutil.TimeStamp
+	Stopped timeutil.TimeStamp
+	// PreviousDuration is used for recording previous duration
+	PreviousDuration time.Duration
+	Created          timeutil.TimeStamp `xorm:"created"`
+	Updated          timeutil.TimeStamp `xorm:"updated"`
 }
 
 func init() {
@@ -118,7 +121,7 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error {
 }
 
 func (run *ActionRun) Duration() time.Duration {
-	return calculateDuration(run.Started, run.Stopped, run.Status)
+	return calculateDuration(run.Started, run.Stopped, run.Status) + run.PreviousDuration
 }
 
 func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) {
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 3b4ac24a2c38..21675cab8ae1 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -554,6 +554,8 @@ var migrations = []Migration{
 	NewMigration("Add combined Index to issue_user.uid and issue_id", v1_22.AddCombinedIndexToIssueUser),
 	// v284 -> v285
 	NewMigration("Add ignore stale approval column on branch table", v1_22.AddIgnoreStaleApprovalsColumnToProtectedBranchTable),
+	// v285 -> v286
+	NewMigration("Add PreviousDuration to ActionRun", v1_22.AddPreviousDurationToActionRun),
 }
 
 // GetCurrentDBVersion returns the current db version
diff --git a/models/migrations/v1_22/v285.go b/models/migrations/v1_22/v285.go
new file mode 100644
index 000000000000..c0dacd40bcdd
--- /dev/null
+++ b/models/migrations/v1_22/v285.go
@@ -0,0 +1,18 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import (
+	"time"
+
+	"xorm.io/xorm"
+)
+
+func AddPreviousDurationToActionRun(x *xorm.Engine) error {
+	type ActionRun struct {
+		PreviousDuration time.Duration
+	}
+
+	return x.Sync(&ActionRun{})
+}
diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go
index 1cdae32a32fe..9cda30d23dc7 100644
--- a/routers/web/repo/actions/view.go
+++ b/routers/web/repo/actions/view.go
@@ -279,6 +279,17 @@ func Rerun(ctx *context_module.Context) {
 		return
 	}
 
+	// reset run's start and stop time when it is done
+	if run.Status.IsDone() {
+		run.PreviousDuration = run.Duration()
+		run.Started = 0
+		run.Stopped = 0
+		if err := actions_model.UpdateRun(ctx, run, "started", "stopped", "previous_duration"); err != nil {
+			ctx.Error(http.StatusInternalServerError, err.Error())
+			return
+		}
+	}
+
 	job, jobs := getRunJobs(ctx, runIndex, jobIndex)
 	if ctx.Written() {
 		return