Skip to content

Commit 013452b

Browse files
Ensure Milestone due_on always gets set to desired date (#133)
The "Should have the expected due_on date" UT was failing, but only at certain times of the day. Further investigation uncovered 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 In the event that the post goes away at some point, I will archive what it says here: > This is an artifact of how GitHub was originally designed. > To my recollection, all timestamps in the database are > normalized to Pacific time. So yes, this is the expected behavior. > [The time used will vary] because midnight Pacific time is > 7AM or 8AM UTC time depending on whether Pacific time is in > daylight savings or not on that date. Given this information, the problem was then quite clear. Examples: * If you set 'due_on' to be '2020-09-24T06:59:00Z', GitHub considers that to be '2020-09-23T07:00:00Z' (the previous day!!) * And if you set 'due_on' to be '2020-09-24T07:01:00Z', GitHub considers that to be '2020-09-24T07:00:00Z' (the correct day) Given this, I've modified `New-GitHubMilestone` and `Set-GitHubMilestone` to drop the user's provided time (since GitHub does that anyway), and instead always add 9 hours from midnight (UTC) to the provided date, which bypasses having to check if we're in daylight savings time or not. I then added two additional UT's to ensure we don't lose that functionality. Finally, I updated the documentation in those methods to try to make it more clear to users what is going to happen with the date/time that they provide. Fixes #92
1 parent f9122db commit 013452b

File tree

2 files changed

+73
-7
lines changed

2 files changed

+73
-7
lines changed

GitHubMilestones.ps1

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Copyright (c) Microsoft Corporation. All rights reserved.
22
# Licensed under the MIT License.
33

4+
# For more information refer to"
5+
# 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
6+
$script:minimumHoursToEnsureDesiredDateInPacificTime = 9
7+
48
function Get-GitHubMilestone
59
{
610
<#
@@ -190,6 +194,8 @@ function New-GitHubMilestone
190194
191195
.PARAMETER DueOn
192196
The milestone due date.
197+
GitHub will drop any time provided with this value, therefore please ensure that the
198+
UTC version of this value has your desired date.
193199
194200
.PARAMETER AccessToken
195201
If provided, this will be used as the AccessToken for authentication with the
@@ -205,6 +211,18 @@ function New-GitHubMilestone
205211
New-GitHubMilestone -OwnerName Microsoft -RepositoryName PowerShellForGitHub -Title "Testing this API"
206212
207213
Creates a new Github milestone for the Microsoft\PowerShellForGitHub project.
214+
215+
.NOTES
216+
For more information on how GitHub handles the dates specified in DueOn, please refer to
217+
this support forum post:
218+
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
219+
220+
Please note that due to artifacts of how GitHub was originally designed, all timestamps
221+
in the GitHub database are normalized to Pacific Time. This means that any dates specified
222+
that occur before 7am UTC will be considered timestamps for the _previous_ day.
223+
224+
Given that GitHub drops the _time_ aspect of this DateTime, this function will ensure that
225+
the requested DueOn date specified is honored by manipulating the time as needed.
208226
#>
209227
[CmdletBinding(
210228
SupportsShouldProcess,
@@ -265,8 +283,15 @@ function New-GitHubMilestone
265283

266284
if ($PSBoundParameters.ContainsKey('DueOn'))
267285
{
268-
$DueOnFormattedTime = $DueOn.ToUniversalTime().ToString('o')
269-
$hashBody.add('due_on', $DueOnFormattedTime)
286+
# If you set 'due_on' to be '2020-09-24T06:59:00Z', GitHub considers that to be '2020-09-23T07:00:00Z'
287+
# And if you set 'due_on' to be '2020-09-24T07:01:00Z', GitHub considers that to be '2020-09-24T07:00:00Z'
288+
# SO....we can't depend on the typical definition of midnight when trying to specify a specific day.
289+
# Instead, we'll use 9am on the designated date to ensure we're always dealing with the
290+
# same date that GitHub uses, regardless of the current state of Daylight Savings Time.
291+
# (See .NOTES for more info)
292+
$modifiedDueOn = $DueOn.ToUniversalTime().date.AddHours($script:minimumHoursToEnsureDesiredDateInPacificTime)
293+
$dueOnFormattedTime = $modifiedDueOn.ToString('o')
294+
$hashBody.add('due_on', $dueOnFormattedTime)
270295
}
271296

272297
$params = @{
@@ -318,6 +343,8 @@ function Set-GitHubMilestone
318343
319344
.PARAMETER DueOn
320345
The milestone due date.
346+
GitHub will drop any time provided with this value, therefore please ensure that the
347+
UTC version of this value has your desired date.
321348
322349
.PARAMETER AccessToken
323350
If provided, this will be used as the AccessToken for authentication with the
@@ -333,6 +360,18 @@ function Set-GitHubMilestone
333360
Set-GitHubMilestone -OwnerName Microsoft -RepositoryName PowerShellForGitHub -Milestone 1 -Title "Testing this API"
334361
335362
Update an existing milestone for the Microsoft\PowerShellForGitHub project.
363+
364+
.NOTES
365+
For more information on how GitHub handles the dates specified in DueOn, please refer to
366+
this support forum post:
367+
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
368+
369+
Please note that due to artifacts of how GitHub was originally designed, all timestamps
370+
in the GitHub database are normalized to Pacific Time. This means that any dates specified
371+
that occur before 7am UTC will be considered timestamps for the _previous_ day.
372+
373+
Given that GitHub drops the _time_ aspect of this DateTime, this function will ensure that
374+
the requested DueOn date specified is honored by manipulating the time as needed.
336375
#>
337376
[CmdletBinding(
338377
SupportsShouldProcess,
@@ -398,8 +437,15 @@ function Set-GitHubMilestone
398437

399438
if ($PSBoundParameters.ContainsKey('DueOn'))
400439
{
401-
$DueOnFormattedTime = $DueOn.ToUniversalTime().ToString('o')
402-
$hashBody.add('due_on', $DueOnFormattedTime)
440+
# If you set 'due_on' to be '2020-09-24T06:59:00Z', GitHub considers that to be '2020-09-23T07:00:00Z'
441+
# And if you set 'due_on' to be '2020-09-24T07:01:00Z', GitHub considers that to be '2020-09-24T07:00:00Z'
442+
# SO....we can't depend on the typical definition of midnight when trying to specify a specific day.
443+
# Instead, we'll use 9am on the designated date to ensure we're always dealing with the
444+
# same date that GitHub uses, regardless of the current state of Daylight Savings Time.
445+
# (See .NOTES for more info)
446+
$modifiedDueOn = $DueOn.ToUniversalTime().date.AddHours($script:minimumHoursToEnsureDesiredDateInPacificTime)
447+
$dueOnFormattedTime = $modifiedDueOn.ToString('o')
448+
$hashBody.add('due_on', $dueOnFormattedTime)
403449
}
404450

405451
$params = @{

Tests/GitHubMilestones.tests.ps1

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ try
1717
defaultIssueTitle = "This is a test issue."
1818
defaultMilestoneTitle1 = "This is a test milestone title #1."
1919
defaultMilestoneTitle2 = "This is a test milestone title #2."
20+
defaultMilestoneTitle3 = "This is a test milestone title #3."
21+
defaultMilestoneTitle4 = "This is a test milestone title #4."
2022
defaultEditedMilestoneTitle = "This is an edited milestone title."
2123
defaultMilestoneDescription = "This is a test milestone description."
2224
defaultEditedMilestoneDescription = "This is an edited milestone description."
@@ -33,6 +35,10 @@ try
3335
$newMilestone = New-GitHubMilestone -Uri $repo.svn_url -Title $defaultMilestoneTitle1 -State "Closed" -DueOn $defaultMilestoneDueOn
3436
$existingMilestone = Get-GitHubMilestone -Uri $repo.svn_url -Milestone $newMilestone.number
3537

38+
# We'll be testing to make sure that regardless of the time in the timestamp, we'll get the desired date.
39+
$newMilestoneDueOnEarlyMorning = New-GitHubMilestone -Uri $repo.svn_url -Title $defaultMilestoneTitle2 -State "Closed" -DueOn $defaultMilestoneDueOn.date.AddHours(1)
40+
$newMilestoneDueOnLateEvening = New-GitHubMilestone -Uri $repo.svn_url -Title $defaultMilestoneTitle3 -State "Closed" -DueOn $defaultMilestoneDueOn.date.AddHours(23)
41+
3642
It "Should have the expected title text" {
3743
$existingMilestone.title | Should be $defaultMilestoneTitle1
3844
}
@@ -42,9 +48,23 @@ try
4248
}
4349

4450
It "Should have the expected due_on date" {
51+
# GitHub drops the time that is attached to 'due_on', so it's only relevant
52+
# to compare the dates against each other.
4553
(Get-Date -Date $existingMilestone.due_on).Date | Should be $defaultMilestoneDueOn.Date
4654
}
4755

56+
It "Should have the expected due_on date even if early morning" {
57+
# GitHub drops the time that is attached to 'due_on', so it's only relevant
58+
# to compare the dates against each other.
59+
(Get-Date -Date $newMilestoneDueOnEarlyMorning.due_on).Date | Should be $defaultMilestoneDueOn.Date
60+
}
61+
62+
It "Should have the expected due_on date even if late evening" {
63+
# GitHub drops the time that is attached to 'due_on', so it's only relevant
64+
# to compare the dates against each other.
65+
(Get-Date -Date $newMilestoneDueOnLateEvening.due_on).Date | Should be $defaultMilestoneDueOn.Date
66+
}
67+
4868
It "Should allow the addition of an existing issue" {
4969
Update-GitHubIssue -Uri $repo.svn_url -Issue $issue.number -Milestone $existingMilestone.number
5070
}
@@ -55,7 +75,7 @@ try
5575
$issue = Get-GitHubIssue -Uri $repo.svn_url -Issue $issue.number
5676

5777
It 'Should have the expected number of milestones' {
58-
$existingMilestones.Count | Should be 1
78+
$existingMilestones.Count | Should be 3
5979
}
6080

6181
It 'Should have the expected title text on the first milestone' {
@@ -69,7 +89,7 @@ try
6989
}
7090

7191
Context 'For editing a milestone' {
72-
$newMilestone = New-GitHubMilestone -Uri $repo.svn_url -Title $defaultMilestoneTitle2 -Description $defaultMilestoneDescription
92+
$newMilestone = New-GitHubMilestone -Uri $repo.svn_url -Title $defaultMilestoneTitle4 -Description $defaultMilestoneDescription
7393
$editedMilestone = Set-GitHubMilestone -Uri $repo.svn_url -Milestone $newMilestone.number -Title $defaultEditedMilestoneTitle -Description $defaultEditedMilestoneDescription
7494

7595
It 'Should have a title/description that is not equal to the original title/description' {
@@ -87,7 +107,7 @@ try
87107
$existingMilestones = @(Get-GitHubMilestone -Uri $repo.svn_url -State All -Sort Completeness -Direction Descending)
88108

89109
It 'Should have the expected number of milestones' {
90-
$existingMilestones.Count | Should be 2
110+
$existingMilestones.Count | Should be 4
91111
}
92112

93113
foreach($milestone in $existingMilestones) {

0 commit comments

Comments
 (0)