Skip to content

PowerShell Date and Time

How to work with dates in PowerShell using Get-Date, DateTime objects, and TimeSpan for accurate date arithmetic, formatting, and comparisons.

In PowerShell, dates, calendar timestamps, and time intervals are managed as strongly typed .NET objects rather than raw strings. Point-in-time values are represented by System.DateTime, while time intervals and durations are represented by System.TimeSpan. This object-oriented approach enables accurate date arithmetic, locale-aware formatting, and reliable timestamp comparisons without manual string parsing.

The Get-Date Cmdlet

The Get-Date cmdlet retrieves an object representing the current system date and time according to the local machine's clock and time zone settings.

Consolepowershell
Get-Date
Outputplaintext
Thursday, October 24, 2026 4:45:12 PM

To inspect the underlying structure and available members of the object returned by Get-Date:

Consolepowershell
(Get-Date).GetType().FullName
Outputplaintext
System.DateTime

Constructing Specific Dates

You can construct explicit DateTime instances by passing string literals or named parameters into Get-Date:

Consolepowershell
Get-Date -Date "2026-12-31 23:59:59"

Get-Date -Year 2026 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0
Outputplaintext
Tuesday, December 31, 2026 11:59:59 PM
Wednesday, January 1, 2026 12:00:00 AM

where:

  • -Date accepts a string that PowerShell parses into a DateTime object.
  • Without -Date, Get-Date defaults to the current system date and time.

DateTime Formatting Strings

While Get-Date outputs a DateTime object, automation tasks often require dates formatted as specific strings for log file names, REST API payloads, or database queries. The -Format parameter (or the .ToString() method) formats dates using standard .NET format specifiers.

Consolepowershell
Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Outputplaintext
2026-09-27 21:46:38

where:

  • yyyy = 4-digit year, MM = 2-digit month, dd = 2-digit day.
  • HH = 24-hour format hour, mm = minutes, ss = seconds.

Common Custom Format Specifiers

Specifier Description Example Output
yyyy 4-digit calendar year 2026
MM 2-digit month (01-12) 10
MMM / MMMM Abbreviated / Full month name Oct / October
dd 2-digit day of the month (01-31) 24
dddd Full day name Thursday
HH 2-digit hour in 24-hour clock (00-23) 16
hh 2-digit hour in 12-hour clock (01-12) 04
mm 2-digit minute (00-59) 45
ss 2-digit second (00-59) 12
fff Milliseconds padded to 3 digits 258
tt AM / PM designator PM
K Time zone offset / UTC indicator +02:00 or Z
format-date-examples.ps1powershell
$LogStamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"

$Iso8601 = Get-Date -Format "o"

$DisplayDate = Get-Date -Format "dddd, MMMM dd, yyyy"

Write-Output "Log Timestamp : $LogStamp"
Write-Output "ISO Standard  : $Iso8601"
Write-Output "Display Date  : $DisplayDate"
Consolepowershell
pwsh ./format-date-examples.ps1
Outputplaintext
Log Timestamp : 2026-09-27_21-47-00
ISO Standard  : 2026-09-27T21:47:00.8570272+02:00
Display Date  : Sunday, September 27, 2026

Using .ToString() on a stored DateTime object:

Example of .ToString() Formattingpowershell
(Get-Date).ToString("dddd, MMMM dd, yyyy")
Outputplaintext
Sunday, September 27, 2026

Date Arithmetic

DateTime objects provide built-in methods for date and time calculations, such as calculating expiration dates or past time intervals.

Adding and Subtracting Intervals

Because DateTime objects are immutable, their arithmetic methods return a new DateTime instance representing the calculated point in time:

Method Description
.AddYears(int) Adds or subtracts whole years.
.AddMonths(int) Adds or subtracts whole months.
.AddDays(double) Adds (or subtracts, via negative numbers) calendar days.
.AddHours(double) Adds fractional hours.
.AddMinutes(double) Adds fractional minutes.
.AddSeconds(double) Adds fractional seconds.
.AddMilliseconds(double) Adds fractional milliseconds.
date-math.ps1powershell
$today = Get-Date
$nextWeek = $today.AddDays(7)
$twoHoursAgo = $today.AddHours(-2)

Write-Output "Today: $($today.ToString('yyyy-MM-dd'))"
Write-Output "Next Week: $($nextWeek.ToString('yyyy-MM-dd'))"
Write-Output "Two Hours Ago: $($twoHoursAgo.ToString('yyyy-MM-dd HH:mm'))"

where:

  • .AddDays(7) returns a new DateTime object 7 days in the future.
  • .AddHours(-2) subtracts time by passing a negative value.
  • The original $today variable remains unchanged, since DateTime is a value type.
Consolepowershell
./date-math.ps1
Outputplaintext
Today: 2026-09-27
Next Week: 2026-10-04
Two Hours Ago: 2026-09-27 19:47

A second example calculating retention windows:

Example of Expiration and Cutoffpowershell
$Now = Get-Date

$PasswordExpires = $Now.AddDays(90)

$RetentionCutoff = $Now.AddDays(-14)

Write-Output "Expires: $($PasswordExpires.ToShortDateString())"
Write-Output "Cutoff:  $($RetentionCutoff.ToShortDateString())"
Outputplaintext
Expires: 1/22/2026
Cutoff:  10/10/2026

Comparing Dates

Because DateTime objects encapsulate chronological points in time, you can compare them directly using PowerShell's relational operators (-lt, -gt, -le, -ge, -eq, -ne). The engine compares the actual timestamps rather than their string representations, so no string parsing is needed.

compare-dates.ps1powershell
$deadline = Get-Date "2026-06-01"
$today = Get-Date

if ($today -gt $deadline) {
    Write-Output "Deadline has passed."
} else {
    Write-Output "Deadline is still upcoming."
}

where -gt compares the two DateTime objects chronologically, just like comparing numbers.

Consolepowershell
./compare-dates.ps1
Outputplaintext
Deadline is still upcoming.

A second example using a warning threshold:

compare-dates-threshold.ps1powershell
$CertificateExpiry = Get-Date "2026-11-01 00:00:00"
$WarningThreshold  = (Get-Date).AddDays(30)

if ($CertificateExpiry -lt (Get-Date)) {
    Write-Error "Certificate is expired!"
}
elseif ($CertificateExpiry -le $WarningThreshold) {
    Write-Warning "Certificate expires soon: $CertificateExpiry"
}
else {
    Write-Output "Certificate is valid."
}
Consolepowershell
pwsh ./compare-dates-threshold.ps1
Outputplaintext
WARNING: Certificate expires soon: 11/01/2026 00:00:00

TimeSpan Objects

Subtracting one DateTime from another produces a System.TimeSpan object, representing the duration between the two points in time.

timespan.ps1powershell
$start = Get-Date "2026-01-01"
$end = Get-Date "2026-03-14"

$duration = $end - $start
Write-Output $duration

where:

  • $end - $start returns a TimeSpan object rather than a plain number.
  • TimeSpan exposes properties like .Days, .Hours, .Minutes, and .TotalDays.
Consolepowershell
./timespan.ps1
Outputplaintext
Days              : 72
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 0
Ticks             : 62208000000000
TotalDays         : 72
TotalHours        : 1728
TotalMinutes      : 103680
TotalSeconds      : 6220800
TotalMilliseconds : 6220800000

Inspecting the object type:

Consolepowershell
$StartTime = Get-Date "2026-10-24 08:00:00"
$EndTime   = Get-Date "2026-10-24 10:30:15"

$Duration = $EndTime - $StartTime
$Duration.GetType().FullName
Outputplaintext
System.TimeSpan

The New-TimeSpan Cmdlet

You can also construct a TimeSpan directly using New-TimeSpan, useful for adding a specific duration to a date or representing a fixed interval:

Consolepowershell
$span = New-TimeSpan -Days 3 -Hours 12
(Get-Date) + $span
Outputplaintext
Thursday, October 1, 2026 9:52:01 AM

A maintenance-window example:

Consolepowershell
$MaintenanceWindow = New-TimeSpan -Hours 2 -Minutes 30
$MaintenanceWindow
Outputplaintext
Days              : 0
Hours             : 2
Minutes           : 30
Seconds           : 0
Milliseconds      : 0
Ticks             : 90000000000
TotalDays         : 0.104166666666667
TotalHours        : 2.5
TotalMinutes      : 150
TotalSeconds      : 9000
TotalMilliseconds : 9000000

where:

  • New-TimeSpan builds a TimeSpan object from specified units (-Days, -Hours, -Minutes, etc.).
  • Adding a TimeSpan to a DateTime produces a new, shifted DateTime.

Component Properties vs. Total Properties

When reading values from a TimeSpan object, make sure to distinguish between component properties and total properties:

  • Component Properties (.Days, .Hours, .Minutes, .Seconds): Represent the remaining fraction of that time unit within the larger interval. For a duration of 2 hours and 30 minutes, .Hours returns 2.
  • Total Properties (.TotalDays, .TotalHours, .TotalMinutes, .TotalSeconds): Represent the entire duration expressed as a single floating-point number. For the same duration, .TotalHours returns 2.5 and .TotalMinutes returns 150.

Practical Example: Automated File Retention and Age Audit

The following script scans a directory for files, calculates the age of each file using TimeSpan arithmetic, and flags files that exceed a defined retention threshold:

audit-file-retention.ps1powershell
param (
    [string]$TargetFolder = "$env:TEMP",
    [int]$RetentionDays   = 30
)

$CurrentTime   = Get-Date
$OldestAllowed = $CurrentTime.AddDays(-$RetentionDays)

Get-ChildItem -Path $TargetFolder -File -ErrorAction SilentlyContinue |
    Select-Object -First 4 |
    ForEach-Object {
        $FileAge = $CurrentTime - $_.LastWriteTime

        [PSCustomObject]@{
            FileName       = $_.Name
            LastModified   = $_.LastWriteTime.ToString("yyyy-MM-dd HH:mm")
            AgeInDays      = [math]::Round($FileAge.TotalDays, 1)
            ExceedsPolicy  = ($_.LastWriteTime -lt $OldestAllowed)
            ActionRequired = if ($_.LastWriteTime -lt $OldestAllowed) { "Purge" } else { "Retain" }
        }
    }

where:

  • $CurrentTime.AddDays(-$RetentionDays) calculates the historical cutoff boundary.
  • $_.LastWriteTime retrieves the DateTime timestamp metadata stored by the filesystem provider.
  • $FileAge = $CurrentTime - $_.LastWriteTime produces a TimeSpan object.
  • [math]::Round($FileAge.TotalDays, 1) rounds the total elapsed days to one decimal place.
  • $_.LastWriteTime -lt $OldestAllowed uses direct date comparison to flag out-of-policy files.

Execute the script from the console:

Consolepowershell
pwsh ./audit-file-retention.ps1 -RetentionDays 7
Outputplaintext
FileName       : .ses
LastModified   : 2026-09-27 16:41
AgeInDays      : 0.2
ExceedsPolicy  : False
ActionRequired : Retain

FileName       : 256cb870-fe9d-44ba-97f1-3d3eb570c482.tmp
LastModified   : 2026-09-27 16:42
AgeInDays      : 0.2
ExceedsPolicy  : False
ActionRequired : Retain

FileName       : mat-debug-5124.log
LastModified   : 2026-09-27 11:18
AgeInDays      : 0.4
ExceedsPolicy  : False
ActionRequired : Retain

FileName       : mat-debug-7512.log
LastModified   : 2026-09-27 11:30
AgeInDays      : 0.4
ExceedsPolicy  : False
ActionRequired : Retain
Navigation