Created
February 11, 2019 23:25
-
-
Save exactmike/517c5005319952c785a191c6143ca467 to your computer and use it in GitHub Desktop.
Get-DateSeries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Given a start date, gets a series of dates for a specified interval and units and limit | |
.DESCRIPTION | |
Given a start date, Gets a series of dates for a specified interval (like 7), and units (like days), and limit (the number of results you want in the series). | |
For example, You can get every 14th day from this Friday for the next 10 sets of 14 days. | |
Or, you can get every 4th minute for the next 400 minutes by specifying limit 100, units minutes, interval 4. | |
.EXAMPLE | |
$vday = Get-Date -Year 2019 -Month 2 -Day 14 -Hour 12 -Minute 0 -Second 0 | |
Get-DateSeries -Start $vday -Interval 14 -Units Days -Limit 10 | |
Thursday, February 14, 2019 12:00:00 PM | |
Thursday, February 28, 2019 12:00:00 PM | |
Thursday, March 14, 2019 12:00:00 PM | |
Thursday, March 28, 2019 12:00:00 PM | |
Thursday, April 11, 2019 12:00:00 PM | |
Thursday, April 25, 2019 12:00:00 PM | |
Thursday, May 9, 2019 12:00:00 PM | |
Thursday, May 23, 2019 12:00:00 PM | |
Thursday, June 6, 2019 12:00:00 PM | |
Thursday, June 20, 2019 12:00:00 PM | |
NOTE:Date input and output format results may differ depending on your Culture settings. | |
From (and including) the Start, gets a datetime object for the 10 dates with each date being 14 days apart. | |
.EXAMPLE | |
$vday = Get-Date -Year 2019 -Month 2 -Day 14 -Hour 12 -Minute 0 -Second 0 | |
Get-DateSeries -Start $vday -Interval 14 -Units Days -Limit 10 -SkipStart | |
Thursday, February 28, 2019 12:00:00 PM | |
Thursday, March 14, 2019 12:00:00 PM | |
Thursday, March 28, 2019 12:00:00 PM | |
Thursday, April 11, 2019 12:00:00 PM | |
Thursday, April 25, 2019 12:00:00 PM | |
Thursday, May 9, 2019 12:00:00 PM | |
Thursday, May 23, 2019 12:00:00 PM | |
Thursday, June 6, 2019 12:00:00 PM | |
Thursday, June 20, 2019 12:00:00 PM | |
Thursday, July 4, 2019 12:00:00 PM | |
NOTE:Date input and output format results may differ depending on your Culture settings. | |
From the Start, gets a datetime object for the next 10 dates with each date being 14 days apart. -SkipStart excludes the start date from the result set. | |
.EXAMPLE | |
Get-DateSeries -Start '2019-02-14 11:30:00' -Interval 5 -Units Minutes -Limit 10 | |
Thursday, February 14, 2019 11:30:00 AM | |
Thursday, February 14, 2019 11:35:00 AM | |
Thursday, February 14, 2019 11:40:00 AM | |
Thursday, February 14, 2019 11:45:00 AM | |
Thursday, February 14, 2019 11:50:00 AM | |
Thursday, February 14, 2019 11:55:00 AM | |
Thursday, February 14, 2019 12:00:00 PM | |
Thursday, February 14, 2019 12:05:00 PM | |
Thursday, February 14, 2019 12:10:00 PM | |
Thursday, February 14, 2019 12:15:00 PM | |
NOTE:Date input and output format results may differ depending on your Culture settings. | |
Gets a date time object for every 5 minutes from 11:30:00 through 12:15:00 | |
.INPUTS | |
DateTime | |
.OUTPUTS | |
DateTime | |
#> | |
function Get-DateSeries | |
{ | |
[CmdletBinding()] | |
[Alias('gds')] | |
[OutputType([DateTime[]])] | |
Param | |
( | |
# Specifies a DateTime object from which to start the series calculation. Values that can be dynamically converted by PowerShell to DateTime are also acceptable. Is included in the series output unless -SkipStart is specified. | |
[Parameter( | |
Mandatory, | |
Position = 0, | |
ValueFromPipeline = $true, | |
ValueFromPipelineByPropertyName = $true | |
)] | |
[datetime] | |
$Start, | |
# Specifies the value to use as the interval between datetime objects in the series in the Units specified in -Units. | |
[Parameter( | |
Mandatory, | |
Position = 1 | |
)] | |
[ValidateRange(1, [int]::MaxValue)] | |
[int] | |
$Interval, | |
# Specifies the value to use for the interval of time Units to create the series. | |
[Parameter( | |
Mandatory, | |
Position = 2 | |
)] | |
[ValidateSet('Milliseconds','Seconds','Minutes','Hours','Days','Weeks','Months','Years')] | |
[string] | |
$Units, | |
# Specifies how many results to include in the series | |
[Parameter( | |
Mandatory, | |
Position = 3 | |
)] | |
[ValidateRange(1,[int]::MaxValue)] | |
[Int] | |
$Limit | |
, | |
# Specifies to NOT include the Start datetime in the series. Otherwise, the start datetime is included. | |
[Parameter( | |
Position = 4 | |
)] | |
[switch] | |
$SkipStart | |
) | |
begin | |
{ | |
} | |
process | |
{ | |
$iteration = 0 | |
if ($true -ne $SkipStart) | |
{ | |
$Start | |
$iteration++ | |
} | |
$outputDate = $Start | |
while ($iteration -lt $Limit) { | |
$iteration++ | |
$nextDate = $( | |
Switch ($Units) | |
{ | |
'Milliseconds' | |
{ | |
$outputDate.AddMilliseconds($Interval) | |
} | |
'Seconds' | |
{ | |
$outputDate.AddSeconds($Interval) | |
} | |
'Minutes' | |
{ | |
$outputDate.AddMinutes($Interval) | |
} | |
'Hours' | |
{ | |
$outputDate.AddHours($Interval) | |
} | |
'Days' | |
{ | |
$outputDate.AddDays($Interval) | |
} | |
'Weeks' | |
{ | |
$intervalInDays = $Interval * 7 | |
$outputDate.AddDays($intervalInDays) | |
} | |
'Months' | |
{ | |
$outputDate.AddMonths($Interval) | |
} | |
'Years' | |
{ | |
$outputDate.AddYears($Interval) | |
} | |
} | |
) | |
$nextDate | |
$outputDate = $nextDate | |
} | |
} | |
end | |
{ | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$CommandName = $MyInvocation.MyCommand.Name.Replace(".Tests.ps1", "") | |
Describe "$CommandName Unit Tests" -Tag 'UnitTests' { | |
Context "Validate parameters" { | |
$defaultParamCount = 11 | |
[object[]]$params = (Get-ChildItem "function:\$CommandName").Parameters.Keys | |
$knownParameters = 'Start','Interval','Units','Limit','SkipStart' | |
$paramCount = $knownParameters.Count | |
It "Should contain specific parameters" { | |
( (Compare-Object -ReferenceObject $knownParameters -DifferenceObject $params -IncludeEqual | Where-Object SideIndicator -eq "==").Count ) | Should Be $paramCount | |
} | |
It "Should only contain $paramCount parameters" { | |
$params.Count - $defaultParamCount | Should Be $paramCount | |
} | |
} | |
} | |
Describe "$commandname Integration Tests" -Tags "IntegrationTests" { | |
BeforeAll { | |
$vday = Get-Date -Year 2019 -Month 2 -Day 14 -Hour 12 -Minute 0 -Second 0 | |
} | |
AfterAll { | |
} | |
Context "Validates Input" { | |
It "Binds only values that are dateTime to the Start parameter" { | |
{Get-DateSeries -Start 'tomorrow' -Interval 3 -Units Days -Limit 3 } | Should Throw | |
{Get-DateSeries -Start '2019-02-14' -Interval 3 -Units Days -Limit 3} | Should NOT Throw | |
{Get-DateSeries -Start '2019-02-14 11:30:00' -Interval 5 -Units Minutes -Limit 10} | Should NOT Throw | |
{Get-DateSeries -Start $vday -Interval 3 -Units Days -Limit 3} | Should NOT Throw | |
} | |
It "Binds only values that are integers to the Interval parameter" { | |
{Get-DateSeries -Start $vday -Interval 4 -Units Days -Limit 3} | Should NOT Throw | |
{Get-DateSeries -Start $vday -Interval 'four' -Units Days -Limit 3} | Should Throw | |
} | |
It "Binds only values that are in the valid set to the Units parameter" { | |
{Get-DateSeries -Start $vday -Interval 4 -Units Days -Limit 3} | Should NOT Throw | |
{Get-DateSeries -Start $vday -Interval 4 -Units 'Decades' -Limit 3} | Should Throw | |
} | |
It "Binds only values that are integers in the ValidateRange to the Limit parameter" { | |
{Get-DateSeries -Start $vday -Interval 4 -Units Days -Limit 3} | Should NOT Throw | |
{Get-DateSeries -Start $vday -Interval 2 -Units Days -Limit 'five'} | Should Throw | |
{Get-DateSeries -Start $vday -Interval 2 -Units Days -Limit 0} | Should Throw | |
} | |
} | |
Context "Produces Expected Output" { | |
It "Produces the expected number of results" { | |
(Get-DateSeries -Start $vday -Interval 4 -Units Days -Limit 5).count | Should Be 5 | |
(Get-DateSeries -Start $vday -Interval 2 -Units Days -Limit 1 -SkipStart).count | Should Be 1 | |
} | |
$TestCases = @( | |
@{ | |
Interval = 1 | |
Units = 'Milliseconds' | |
} | |
@{ | |
Interval = 5 | |
Units = 'Milliseconds' | |
} | |
@{ | |
Interval = 1 | |
Units = 'Seconds' | |
} | |
@{ | |
Interval = 5 | |
Units = 'Seconds' | |
} | |
@{ | |
Interval = 1 | |
Units = 'Minutes' | |
} | |
@{ | |
Interval = 5 | |
Units = 'Minutes' | |
} | |
@{ | |
Interval = 1 | |
Units = 'Hours' | |
} | |
@{ | |
Interval = 5 | |
Units = 'Hours' | |
} | |
@{ | |
Interval = 1 | |
Units = 'Days' | |
} | |
@{ | |
Interval = 5 | |
Units = 'Days' | |
} | |
) | |
It -TestCases $TestCases "Produces the expected intervals with built-in datetime units" { | |
param($Interval,$Units) | |
$results = Get-DateSeries -Start $vday -Interval $Interval -Units $Units -Limit 2 | |
$($results[1]-$results[0]).$('Total'+ $Units) | Should Be $Interval | |
} | |
$TestCases = @( | |
@{ | |
Interval = 1 | |
Units = 'Weeks' | |
} | |
@{ | |
Interval = 5 | |
Units = 'Weeks' | |
} | |
@{ | |
Interval = 1 | |
Units = 'Years' | |
} | |
@{ | |
Interval = 5 | |
Units = 'Years' | |
} | |
) | |
It -TestCases $TestCases "Produces the expected intervals with additional Units" { | |
param($Interval,$Units) | |
$results = Get-DateSeries -Start $vday -Interval $Interval -Units $Units -Limit 2 | |
switch ($Units) | |
{ | |
'Years' | |
{ | |
switch ($Interval) | |
{ | |
{$_ -lt 4} | |
{ | |
$comparison = @($(365*$Interval);$(365*$interval) + 1) | |
} | |
{$_ -eq 4} | |
{ | |
$comparison = @($(365*$interval)+1) | |
} | |
{$_ -gt 4} | |
{ | |
if ($interval%4 -eq 0) | |
{$add = $Interval/4} | |
else | |
{$add = [math]::Truncate($($interval/4))} | |
$base = $Interval * 365 | |
$comparison = @($($base + $add);$($base + $add + 1)) | |
} | |
} | |
$($results[1]-$results[0]).TotalDays | Should BeIn $comparison | |
} | |
'Weeks' | |
{ | |
$comparison = $interval * 7 | |
$($results[1]-$results[0]).TotalDays | Should Be $comparison | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment