modules/Helper/DateTimeFormula.psm1
class DateTimeFormula{ hidden [string] $referentUnit hidden [bool] $isReferentNegative hidden [int] $referentValue hidden [string] $timespanUnit hidden [bool] $isFormula [string] $formula [datetime] $datetime DateTimeFormula([string]$formula){ $this.formula = $formula $this.identifyUnits() try { $this.datetime = $this.parseDateTime() } catch { throw ("Invalid date value: $formula") } } [datetime] applyTimeSpanFormula([string]$formula){ return $this.applyTimeSpanFormula($this.datetime, $this.splitDateFormula($formula)) } hidden [void] identifyUnits() { if ($this.formula.SubString(0,1) -eq '-') { $this.isReferentNegative = $true $this.formula = $this.formula.SubString(1) } else { $this.isReferentNegative = $false } if ($this.formula.SubString(0, 1) -cin ('Y', 'M', 'D', 'h', 'm')) { $this.referentUnit = $this.formula.SubString(0, 1) $haveValue = $false for($i=1; $i -lt $this.formula.Length; $i++){ if ($this.formula[$i] -cin ('Y', 'Q', 'M', 'D', 'W', 'D', 'h', 'm', 's')){ $this.referentValue = $this.formula.SubString(1, $i) $this.timespanUnit = $this.formula.SubString($i) $haveValue = $true break } } if (-not $haveValue){ $this.referentValue = $this.formula.SubString(1) $this.timespanUnit = '' } $this.isFormula = $true } elseif ($this.formula.SubString(0, 1) -ceq 'C') { $this.referentUnit = $this.formula.SubString(0, 2) $this.timespanUnit = $this.formula.SubString(2) $this.isFormula = $true } elseif ($this.formula.SubString(0, 2) -ceq 'WD') { $this.referentUnit = $this.formula.SubString(0, 2) if ($this.formula.Length -gt 2){ $this.referentValue = $this.formula.SubString(2, 1) $this.timespanUnit = $this.formula.SubString(3) } else { $this.referentValue = '0' $this.timespanUnit = '' } $this.isFormula = $true } else { $this.isFormula = $false } } hidden [datetime] parseDateTime(){ $retValue = $null if ($this.isFormula) { $retValue = $this.getReferentDate($this.referentUnit) if ($this.timespanUnit) { $dt = $this.splitDateFormula($this.timespanUnit) $retValue = $this.applyTimeSpanFormula($retValue, $dt) } else { return $retValue } } else { try { $retValue = [datetime]::parse($this.formula) } catch { throw ('Invalid date formula: {0}' -f @($this.formula, $_)) } } return $retValue } hidden [datetime] applyTimeSpanFormula([datetime]$datetime, [PSCustomObject]$exp){ $retValue = $datetime foreach ($node in $exp.nodes) { switch -CaseSensitive ($node.unit) { 'Y' { $retValue = $retValue.AddYears.($node.number) } 'Q' { $retValue = $retValue.AddMonths(3 * $node.number) } 'M' { $retValue = $retValue.AddMonths($node.number) } 'W' { $retValue = $retValue.AddDays(7 * $node.number) } 'D' { $retValue = $retValue.AddDays($node.number) } 'h' { $retValue = $retValue.AddHours($node.number) } 'm' { $retValue = $retValue.AddMinutes($node.number) } 's' { $retValue = $retValue.AddSeconds($node.number) } } } return $retValue } hidden [datetime] getReferentDate([string]$value){ $date = Get-Date switch -CaseSensitive ($value){ 'CT' { $date = (Get-Date) } 'CY' { $date = (Get-Date -Year $date.Year -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0 -Millisecond 0) } 'CQ' { $date = (Get-Date -Year $date.Year -Month (3 * [Math]::Floor($date.Month / 3)) -Day 1 -Hour 0 -Minute 0 -Second 0 -Millisecond 0) } 'CM' { $date = (Get-Date -Year $date.Year -Month $date.Month -Day 1 -Hour 0 -Minute 0 -Second 0 -Millisecond 0) } 'CW' { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour 0 -Minute 0 -Second 0 -Millisecond 0).AddDays(-$date.DayOfWeek) } 'CD' { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour 0 -Minute 0 -Second 0 -Millisecond 0) } 'Ch' { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour $date.Hour -Minute 0 -Second 0 -Millisecond 0) } 'Cm' { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour $date.Hour -Minute $date.Minute -Second 0 -Millisecond 0) } 'Y' { if ($this.isReferentNegative) { $date = (Get-Date -Year $date.Year -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0 -Millisecond 0).AddYears(-$this.referentValue) } else { $date = (Get-Date -Year $this.referentValue -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0 -Millisecond 0) } } 'M' { if ($this.isReferentNegative) { $date = (Get-Date -Year $date.Year -Month $date.Month -Day 1 -Hour 0 -Minute 0 -Second 0 -Millisecond 0).AddMonths(-$this.referentValue) } else { $date = (Get-Date -Year $date.Year -Month $this.referentValue -Day 1 -Hour 0 -Minute 0 -Second 0 -Millisecond 0) } } 'D' { if ($this.isReferentNegative) { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour 0 -Minute 0 -Second 0 -Millisecond 0).AddDays(-$this.referentValue) } else { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $this.referentValue -Hour 0 -Minute 0 -Second 0 -Millisecond 0) } } 'h' { if ($this.isReferentNegative) { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour $date.Hour -Minute 0 -Second 0 -Millisecond 0).AddHours(-$this.referentValue) } else { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour $this.referentValue -Minute 0 -Second 0 -Millisecond 0) } } 'm' { if ($this.isReferentNegative) { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour $date.Hour -Minute $date.Minute -Second 0 -Millisecond 0).AddMinutes(-$this.referentValue) } else { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour $date.Hour -Minute $this.referentValue -Second 0 -Millisecond 0) } } 'WD' { if ($this.isReferentNegative) { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour 0 -Minute 0 -Second 0 -Millisecond 0).AddDays(-7).AddDays(-($date.DayOfWeek-$this.referentValue)) } else { $date = (Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour 0 -Minute 0 -Second 0 -Millisecond 0).AddDays(-($date.DayOfWeek-$this.referentValue)) } } default { $date = $null } } return $date } hidden [PSCustomObject] splitDateFormula([string] $value){ $retValue = [PSCustomObject]@{expression=$value; nodes=@()} $prev=0 for($i=0; $i -lt $value.Length; $i++){ if ($value[$i] -cin ('Y', 'Q', 'M', 'D', 'W', 'D', 'h', 'm', 's')){ $number = $value.Substring($prev, $i-$prev) $unit = $value.Substring($i, 1) $prev = $i + 1 $retValue.nodes += [PSCustomObject]@{number=[int]$number; unit=$unit} } } return $retValue } } |