PoshCode Logo PowerShell Code Repository

IsoDates.psm1 by Joel Bennett 5 years ago
embed code: <script type="text/javascript" src="http://PoshCode.org/embed/966"></script>download | new post

A handful of functions for returning IS0-8601 formatted dates and parsing them. All functions work (even in the pipeline) in both PowerShell 1 and 2.

  1. #requires -version 1.0
  2. # or version 2.0, obviously
  3. ## ISO 8601 Dates
  4. ########################################################################
  5. ## Copyright (c) Joel Bennett, 2009
  6. ## Free for use under GPL, MS-RL, MS-PL, or BSD license. Your choice.
  7. function Get-ISODate {
  8. #.Synopsis
  9. #  Get the components of an ISO 8601 date: year, week number, day of week
  10. #.Description
  11. #  For any given date you get an array of year, week, day that you can use
  12. #  as part of a string format....
  13. #.Parameter Date
  14. #  The date you want to analyze. Accepts dates on the pipeline
  15. Param([DateTime]$date=$(Get-Date))
  16. Process {
  17.   if($_){$date=$_}
  18.   ## Get Jan 1st of that year
  19.   $startYear  = Get-Date -Date $date -Month 1 -Day 1
  20.   ## Get Dec 31st of that year
  21.   $endYear    = Get-Date -Date $date -Month 12 -Day 31
  22.   ## ISO 8601 weeks are Monday-Sunday, with days marked 1-7
  23.   ## But .Net's DayOfWeek enum is 0 for Sunday through 6 for saturday
  24.   $dayOfWeek  = @(7,1,2,3,4,5,6)[$date.DayOfWeek]
  25.   $lastofWeek = @(7,1,2,3,4,5,6)[$endYear.DayOfWeek]
  26.   ## By definition: the first week of a year is the one which
  27.   ##           includes the first Thursday, and thus, January 4th
  28.   $adjust     = @(6,7,8,9,10,4,5)[$startYear.DayOfWeek]
  29.  
  30.   switch([Math]::Floor((($date.Subtract($startYear).Days + $adjust)/7)))
  31.   {
  32.     0 {
  33.       ## Return weeknumber of dec 31st of the previous year
  34.       ## But return THIS dayOfWeek
  35.       Write-Output @(
  36.          @(Get-ISODate $startYear.AddDays(-1))[0,1] + @(,$dayOfWeek))
  37.     }
  38.     53 {
  39.       ## If dec 31st falls before thursday it is week 01 of next year
  40.       if ($lastofWeek -lt 4) {
  41.         Write-Output @(($date.Year + 1), 1, $dayOfWeek)
  42.       } else {
  43.         Write-Output @($date.Year, $_, $dayOfWeek)
  44.       }
  45.     }
  46.     default {
  47.       Write-Output @($date.Year, $_, $dayOfWeek)
  48.     }
  49.   }
  50. }
  51. }
  52.  
  53. function Get-ISOWeekOfYear {
  54. #.Synopsis
  55. #  Get the correct (according to ISO 8601) week number
  56. #.Description
  57. #  For any given date you get the week of the year, according to ISO8610
  58. #.Parameter Date
  59. #  The date you want to analyze. Accepts dates on the pipeline
  60. Param([DateTime]$date=$(Get-Date))
  61. Process {
  62.   if($_){$date=$_}
  63.   @(Get-ISODate $date)[1]
  64. }
  65. }
  66.  
  67. function Get-ISOYear {
  68. #.Synopsis
  69. #  Get the correct (according to ISO 8601) year number
  70. #.Description
  71. #  For any given date you get the year number, according to ISO8610 ...
  72. #  for some days at the begining or end of year, it reports the previous
  73. #  or the next year (because ISO defines those days as part of the first
  74. #  or last week of the adjacent year).
  75. #.Parameter Date
  76. #  The date you want to analyze. Accepts dates on the pipeline
  77. Param([DateTime]$date=$(Get-Date))
  78. Process {
  79.   if($_){$date=$_}
  80.   @(Get-ISODate $date)[0]
  81. }
  82. }
  83.  
  84. function Get-ISODayOfWeek {
  85. #.Synopsis
  86. #  Get the correct (according to ISO 8601) day of the week
  87. #.Description
  88. #  For any given date you get the day of the week, according to ISO8610
  89. #.Parameter Date
  90. #  The date you want to analyze. Accepts dates on the pipeline
  91. Param([DateTime]$date=$(Get-Date))
  92. Process {
  93.   if($_){$date=$_}
  94.   @(7,1,2,3,4,5,6)[$date.DayOfWeek]
  95. }
  96. }
  97.  
  98. function Get-ISODateString {
  99. #.Synopsis
  100. #  Get the correctly formatted (according to ISO 8601) date string
  101. #.Description
  102. #  For any given date you get the date string, according to ISO8610,
  103. #  like: 2009-W12-4  for Thursday, March 19th, 2009
  104. #.Parameter Date
  105. #  The date you want to analyze. Accepts dates on the pipeline
  106. Param([DateTime]$date=$(Get-Date))
  107. Process {
  108.   if($_){$date=$_}
  109.   "{0}-W{1:00}-{2}" -f @(Get-ISODate $date)
  110. }
  111. }
  112.  
  113. function ConvertFrom-ISODateString {
  114. #.Synopsis
  115. #  Parses ISO 8601 Date strings in the format: 2009-W12-4 to DateTime
  116. #.Description
  117. #  Allows converting ISO-formated date strings back into actual objects
  118. #.Parameter Date
  119. #  An ISO8601 date, like:
  120. #    2009-W12-4 for Thursday, March 19th, 2009
  121. #    1999-W52-6 for Saturday, January 1st, 2000
  122. #    2000-W01-1 for Monday, January 3rd, 2000
  123. Param([string]$date)
  124. Process {
  125.   if($_){$date=$_}
  126.   if($date -notmatch "\d{4}-W\d{2}-\d") {
  127.     Write-Error "The string is not an ISO 8601 formatted date string"
  128.   }
  129.   $ofs = ""
  130.   $year = [int]"$($date[0..3])"
  131.   $week = [int]"$($date[6..7])"
  132.   $day  = [int]"$($date[9])"
  133.  
  134.   $firstOfYear = Get-Date -year $year -day 1  -month 1
  135.   $days = 7*$week - ((Get-ISODayOfWeek $firstOfYear) - $day)
  136.  
  137.   $result = $firstOfYear.AddDays( $days )
  138.   if(($result.Year -ge $year) -and ((Get-ISODayOfWeek $firstOfYear) -le 4) ) {
  139.    return $firstOfYear.AddDays( ($days - 7) )
  140.   } else {
  141.    return $result
  142.   }
  143. }
  144. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me