-
Notifications
You must be signed in to change notification settings - Fork 29
/
ConvertFrom-Duration.ps1
96 lines (83 loc) · 2.96 KB
/
ConvertFrom-Duration.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<#
.SYNOPSIS
Parses a Timespan from a ISO8601 duration string.
.INPUTS
System.String containing an ISO8601 duration.
.OUTPUTS
System.Timespan containing the duration, as parsed and converted to a Timespan.
.FUNCTIONALITY
Date and time
.LINK
https://en.wikipedia.org/wiki/ISO_8601#Durations
.LINK
Import-Variables.ps1
.LINK
Test-Variable.ps1
.LINK
Stop-ThrowError.ps1
.EXAMPLE
"$(ConvertFrom-Duration.ps1 P1D)"
1.00:00:00
.EXAMPLE
"$(ConvertFrom-Duration.ps1 P3Y6M4DT12H30M5S)"
WARNING: Adding year(s) as a mean number of days (365.2425).
WARNING: Adding month(s) as a mean number of days (30.436875).
1283.12:30:05
#>
#Requires -Version 7
[CmdletBinding()][OutputType([timespan])] Param(
<#
An ISO8601 duration string in one of four formats:
* PnYnMnDTnHnMnS
* PnW
* Pyyyy-MM-ddTHH:mm:ss
* PyyyyMMddTHHmmss
#>
[Parameter(Position=0,ValueFromPipeline=$true,ValueFromRemainingArguments)]
[ValidatePattern('\AP(?:T?\d\w+|\d\d\d\d(?:-\d\d){2}T\d\d(?::\d\d){2})\z',
ErrorMessage='An ISO8601 duration is required')]
[string[]] $InputObject,
# Supresses warnings about approximate conversions.
[Alias('Quiet')][switch]$NoWarnings
)
Begin
{
$MeanMonth,$MeanYear = 30.436875,365.2425
[regex[]] $formats = '\AP(?<Weeks>\d+)W\z',
'\AP(?:(?<Years>\d+)Y)?(?:(?<Months>\d+)M)?(?:(?<Days>\d+)D)?(?:T(?:(?<Hours>\d+)H)?(?:(?<Minutes>\d+)M)?(?:(?<Seconds>\d+)S)?)?\z',
'\AP(?<Years>\d{4})-(?<Months>\d{2})-(?<Days>\d{2})T(?<Hours>\d{2}):(?<Minutes>\d{2}):(?<Seconds>\d{2})\z',
'\AP(?<Years>\d{4})(?<Months>\d{2})(?<Days>\d{2})T(?<Hours>\d{2})(?<Minutes>\d{2})(?<Seconds>\d{2})\z'
}
Process
{
foreach($o in $InputObject)
{
[bool]$matched = $false
foreach($f in $formats)
{
if($o -match $f) {$matched = $true; break}
}
if(!$matched)
{
Stop-ThrowError.ps1 "Could not parse '$o' as an ISO8601 duration." -Argument InputObject
}
Import-Variables.ps1 $Matches
[timespan]$value = 0
if(Test-Variable.ps1 Years)
{
if(!$NoWarnings) {Write-Warning "Adding year(s) as a mean number of days ($MeanYear)."}
$value += New-Object Timespan ($MeanYear*[int]$Years),0,0,0
}
if(Test-Variable.ps1 Months)
{
if(!$NoWarnings) {Write-Warning "Adding month(s) as a mean number of days ($MeanMonth)."}
$value += New-Object Timespan ($MeanMonth*[int]$Months),0,0,0
}
if(Test-Variable.ps1 Weeks) {$value += New-Object Timespan (7*[int]$Weeks),0,0,0}
if(Test-Variable.ps1 Days) {$value += New-Object Timespan ([int]$Days),0,0,0}
if(Test-Variable.ps1 Hours) {$value += New-Object Timespan ([int]$Hours),0,0}
if(Test-Variable.ps1 Minutes) {$value += New-Object Timespan 0,([int]$Minutes),0}
if(Test-Variable.ps1 Seconds) {$value += New-Object Timespan 0,0,([int]$Seconds)}
$value
}
}