diff --git a/GitHubMilestones.ps1 b/GitHubMilestones.ps1 index 877cbe94..70eee5ed 100644 --- a/GitHubMilestones.ps1 +++ b/GitHubMilestones.ps1 @@ -1,6 +1,10 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. +# For more information refer to" +# https://github.community/t5/How-to-use-Git-and-GitHub/Milestone-quot-Due-On-quot-field-defaults-to-7-00-when-set-by-v3/m-p/6901 +$script:minimumHoursToEnsureDesiredDateInPacificTime = 9 + function Get-GitHubMilestone { <# @@ -190,6 +194,8 @@ function New-GitHubMilestone .PARAMETER DueOn The milestone due date. + GitHub will drop any time provided with this value, therefore please ensure that the + UTC version of this value has your desired date. .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the @@ -205,6 +211,18 @@ function New-GitHubMilestone New-GitHubMilestone -OwnerName Microsoft -RepositoryName PowerShellForGitHub -Title "Testing this API" Creates a new Github milestone for the Microsoft\PowerShellForGitHub project. + + .NOTES + For more information on how GitHub handles the dates specified in DueOn, please refer to + this support forum post: + https://github.community/t5/How-to-use-Git-and-GitHub/Milestone-quot-Due-On-quot-field-defaults-to-7-00-when-set-by-v3/m-p/6901 + + Please note that due to artifacts of how GitHub was originally designed, all timestamps + in the GitHub database are normalized to Pacific Time. This means that any dates specified + that occur before 7am UTC will be considered timestamps for the _previous_ day. + + Given that GitHub drops the _time_ aspect of this DateTime, this function will ensure that + the requested DueOn date specified is honored by manipulating the time as needed. #> [CmdletBinding( SupportsShouldProcess, @@ -265,8 +283,15 @@ function New-GitHubMilestone if ($PSBoundParameters.ContainsKey('DueOn')) { - $DueOnFormattedTime = $DueOn.ToUniversalTime().ToString('o') - $hashBody.add('due_on', $DueOnFormattedTime) + # If you set 'due_on' to be '2020-09-24T06:59:00Z', GitHub considers that to be '2020-09-23T07:00:00Z' + # And if you set 'due_on' to be '2020-09-24T07:01:00Z', GitHub considers that to be '2020-09-24T07:00:00Z' + # SO....we can't depend on the typical definition of midnight when trying to specify a specific day. + # Instead, we'll use 9am on the designated date to ensure we're always dealing with the + # same date that GitHub uses, regardless of the current state of Daylight Savings Time. + # (See .NOTES for more info) + $modifiedDueOn = $DueOn.ToUniversalTime().date.AddHours($script:minimumHoursToEnsureDesiredDateInPacificTime) + $dueOnFormattedTime = $modifiedDueOn.ToString('o') + $hashBody.add('due_on', $dueOnFormattedTime) } $params = @{ @@ -318,6 +343,8 @@ function Set-GitHubMilestone .PARAMETER DueOn The milestone due date. + GitHub will drop any time provided with this value, therefore please ensure that the + UTC version of this value has your desired date. .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the @@ -333,6 +360,18 @@ function Set-GitHubMilestone Set-GitHubMilestone -OwnerName Microsoft -RepositoryName PowerShellForGitHub -Milestone 1 -Title "Testing this API" Update an existing milestone for the Microsoft\PowerShellForGitHub project. + + .NOTES + For more information on how GitHub handles the dates specified in DueOn, please refer to + this support forum post: + https://github.community/t5/How-to-use-Git-and-GitHub/Milestone-quot-Due-On-quot-field-defaults-to-7-00-when-set-by-v3/m-p/6901 + + Please note that due to artifacts of how GitHub was originally designed, all timestamps + in the GitHub database are normalized to Pacific Time. This means that any dates specified + that occur before 7am UTC will be considered timestamps for the _previous_ day. + + Given that GitHub drops the _time_ aspect of this DateTime, this function will ensure that + the requested DueOn date specified is honored by manipulating the time as needed. #> [CmdletBinding( SupportsShouldProcess, @@ -398,8 +437,15 @@ function Set-GitHubMilestone if ($PSBoundParameters.ContainsKey('DueOn')) { - $DueOnFormattedTime = $DueOn.ToUniversalTime().ToString('o') - $hashBody.add('due_on', $DueOnFormattedTime) + # If you set 'due_on' to be '2020-09-24T06:59:00Z', GitHub considers that to be '2020-09-23T07:00:00Z' + # And if you set 'due_on' to be '2020-09-24T07:01:00Z', GitHub considers that to be '2020-09-24T07:00:00Z' + # SO....we can't depend on the typical definition of midnight when trying to specify a specific day. + # Instead, we'll use 9am on the designated date to ensure we're always dealing with the + # same date that GitHub uses, regardless of the current state of Daylight Savings Time. + # (See .NOTES for more info) + $modifiedDueOn = $DueOn.ToUniversalTime().date.AddHours($script:minimumHoursToEnsureDesiredDateInPacificTime) + $dueOnFormattedTime = $modifiedDueOn.ToString('o') + $hashBody.add('due_on', $dueOnFormattedTime) } $params = @{ diff --git a/Tests/GitHubMilestones.tests.ps1 b/Tests/GitHubMilestones.tests.ps1 index c5a60ceb..9e943908 100644 --- a/Tests/GitHubMilestones.tests.ps1 +++ b/Tests/GitHubMilestones.tests.ps1 @@ -17,6 +17,8 @@ try defaultIssueTitle = "This is a test issue." defaultMilestoneTitle1 = "This is a test milestone title #1." defaultMilestoneTitle2 = "This is a test milestone title #2." + defaultMilestoneTitle3 = "This is a test milestone title #3." + defaultMilestoneTitle4 = "This is a test milestone title #4." defaultEditedMilestoneTitle = "This is an edited milestone title." defaultMilestoneDescription = "This is a test milestone description." defaultEditedMilestoneDescription = "This is an edited milestone description." @@ -33,6 +35,10 @@ try $newMilestone = New-GitHubMilestone -Uri $repo.svn_url -Title $defaultMilestoneTitle1 -State "Closed" -DueOn $defaultMilestoneDueOn $existingMilestone = Get-GitHubMilestone -Uri $repo.svn_url -Milestone $newMilestone.number + # We'll be testing to make sure that regardless of the time in the timestamp, we'll get the desired date. + $newMilestoneDueOnEarlyMorning = New-GitHubMilestone -Uri $repo.svn_url -Title $defaultMilestoneTitle2 -State "Closed" -DueOn $defaultMilestoneDueOn.date.AddHours(1) + $newMilestoneDueOnLateEvening = New-GitHubMilestone -Uri $repo.svn_url -Title $defaultMilestoneTitle3 -State "Closed" -DueOn $defaultMilestoneDueOn.date.AddHours(23) + It "Should have the expected title text" { $existingMilestone.title | Should be $defaultMilestoneTitle1 } @@ -42,9 +48,23 @@ try } It "Should have the expected due_on date" { + # GitHub drops the time that is attached to 'due_on', so it's only relevant + # to compare the dates against each other. (Get-Date -Date $existingMilestone.due_on).Date | Should be $defaultMilestoneDueOn.Date } + It "Should have the expected due_on date even if early morning" { + # GitHub drops the time that is attached to 'due_on', so it's only relevant + # to compare the dates against each other. + (Get-Date -Date $newMilestoneDueOnEarlyMorning.due_on).Date | Should be $defaultMilestoneDueOn.Date + } + + It "Should have the expected due_on date even if late evening" { + # GitHub drops the time that is attached to 'due_on', so it's only relevant + # to compare the dates against each other. + (Get-Date -Date $newMilestoneDueOnLateEvening.due_on).Date | Should be $defaultMilestoneDueOn.Date + } + It "Should allow the addition of an existing issue" { Update-GitHubIssue -Uri $repo.svn_url -Issue $issue.number -Milestone $existingMilestone.number } @@ -55,7 +75,7 @@ try $issue = Get-GitHubIssue -Uri $repo.svn_url -Issue $issue.number It 'Should have the expected number of milestones' { - $existingMilestones.Count | Should be 1 + $existingMilestones.Count | Should be 3 } It 'Should have the expected title text on the first milestone' { @@ -69,7 +89,7 @@ try } Context 'For editing a milestone' { - $newMilestone = New-GitHubMilestone -Uri $repo.svn_url -Title $defaultMilestoneTitle2 -Description $defaultMilestoneDescription + $newMilestone = New-GitHubMilestone -Uri $repo.svn_url -Title $defaultMilestoneTitle4 -Description $defaultMilestoneDescription $editedMilestone = Set-GitHubMilestone -Uri $repo.svn_url -Milestone $newMilestone.number -Title $defaultEditedMilestoneTitle -Description $defaultEditedMilestoneDescription It 'Should have a title/description that is not equal to the original title/description' { @@ -87,7 +107,7 @@ try $existingMilestones = @(Get-GitHubMilestone -Uri $repo.svn_url -State All -Sort Completeness -Direction Descending) It 'Should have the expected number of milestones' { - $existingMilestones.Count | Should be 2 + $existingMilestones.Count | Should be 4 } foreach($milestone in $existingMilestones) {