Last active
December 13, 2022 23:58
-
-
Save gravejester/6bc472fcf60ca3f0eeef to your computer and use it in GitHub Desktop.
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
function Show-Calendar { | |
<# | |
.SYNOPSIS | |
Show calendar. | |
.DESCRIPTION | |
This function is a PowerShell version of the *NIX cal command and will show a | |
calendar of the chosen month(s). The current day will be marked with a '*'. | |
For best results, use together with the FormatPx module by Kirk Munro. | |
.EXAMPLE | |
Show-Calendar | |
Will show a calendar view of the current month. | |
.EXAMPLE | |
Show-Calendar -InvariantCulture | |
Will show a calendar view of the current month, using the Invariant Culture | |
.EXAMPLE | |
Show-Calendar -Culture 'de-DE' | |
Will show a calendar view of the current month, using the de-DE (German) culture. | |
.EXAMPLE | |
Show-Calendar 1 2015 -m 3 | |
Will show a calendar view of the first three months in 2015. | |
.EXAMPLE | |
Show-Calendar 12 -MarkDay 25 -Abbreviated | |
Will show a calendar view of december and mark December 25, with abbreviated day names. | |
.EXAMPLE | |
Show-Calendar 1 2015 -m 12 -MarkDate (Get-Date -Year 2015 -Month 2 -Day 14) | |
Will show a calendar view of 2015 and mark 14th of February. | |
.LINK | |
https://github.com/KirkMunro/FormatPx | |
.NOTES | |
Author: Øyvind Kallstad | |
Date: 21.12.2014 | |
Version: 1.1 | |
22.12.2014 | |
Added Alignment parameter | |
Made the entire function culture aware | |
Added support for abbreviated day names | |
#> | |
[CmdletBinding(DefaultParameterSetName = 'Culture')] | |
param ( | |
# The starting month number. Default is current month. | |
[Parameter(Position = 0)] | |
[Alias('Month')] | |
[ValidateRange(1,12)] | |
[int] $StartMonth = [DateTime]::Now.Month, | |
# The starting year. Default is current year. | |
[Parameter(Position = 1)] | |
[Alias('Year')] | |
[ValidateRange(1,9999)] | |
[int32] $StartYear = [DateTime]::Now.Year, | |
# How many months to show. Default is 1. | |
[Parameter()] | |
[Alias('m')] | |
[ValidateRange(1,[int]::MaxValue)] | |
[int32] $Months = 1, | |
# Day to mark on the calendar. | |
[Parameter()] | |
[ValidateRange(1,31)] | |
[int32] $MarkDay, | |
# Date to mark on the calendar. | |
[Parameter()] | |
[datetime] $MarkDate, | |
# Set alignment of the dates in the output. Default value is 'Right'. | |
[Parameter()] | |
[ValidateSet('Left','Right')] | |
[string] $Alignment = 'Right', | |
# Use the Invariant Culture (English). | |
[Parameter(ParameterSetName = 'InvariantCulture')] | |
[switch] $InvariantCulture, | |
# Use this parameter to choose what culture to use. If this parameter is not used and | |
# the InvariantCulture parameter is false, the current culture will be used instead. | |
[Parameter(ParameterSetName = 'Culture')] | |
[string] $Culture, | |
# Use this parameter to use abbreviated day names. Default is to use the full name of days. | |
[Parameter()] | |
[switch] $AbbreviatedDayNames | |
) | |
function New-DayOfWeekString { | |
<# | |
.SYNPSIS | |
Output a culture aware string of a specified week day. | |
.NOTES | |
Author: Øyvind Kallstad | |
#> | |
[CmdletBinding()] | |
[OutputType([String])] | |
param ( | |
# The day of week in Invariant Culture (English). | |
[Parameter(Position = 0, Mandatory)] | |
[System.DayOfWeek] $DayOfWeek, | |
[Parameter(Position = 1, ValueFromPipeline)] | |
[CultureInfo] $CultureInfo = [System.Globalization.CultureInfo]::CurrentCulture, | |
# Show the week day in an abbreviated form. | |
[Parameter()] | |
[switch] $Abbreviated | |
) | |
if ($Abbreviated) { | |
Write-Output ($cultureInfo.TextInfo.ToTitleCase($cultureInfo.DateTimeFormat.GetAbbreviatedDayName([System.DayOfWeek]::$DayOfWeek))) | |
} | |
else { | |
Write-Output ($cultureInfo.TextInfo.ToTitleCase($cultureInfo.DateTimeFormat.GetDayName([System.DayOfWeek]::$DayOfWeek))) | |
} | |
} | |
function New-Week { | |
<# | |
.SYNOPSIS | |
Returns an ordered dictionary representing a week. | |
.NOTES | |
Author: Øyvind Kallstad | |
#> | |
[CmdletBinding()] | |
[OutputType([System.Collections.Specialized.OrderedDictionary])] | |
param ( | |
[Parameter(Position = 0, ValueFromPipeline)] | |
[CultureInfo] $CultureInfo = [System.Globalization.CultureInfo]::CurrentCulture, | |
# Show the week day in an abbreviated form. | |
[Parameter()] | |
[switch] $Abbreviated | |
) | |
$propHash = @{ | |
CultureInfo = $CultureInfo | |
} | |
if ($Abbreviated) { | |
$propHash.Abbreviated = $true | |
} | |
# define week day names | |
$monday = New-DayOfWeekString 'Monday' @propHash | |
$tuesday = New-DayOfWeekString 'Tuesday' @propHash | |
$wednesday = New-DayOfWeekString 'Wednesday' @propHash | |
$thursday = New-DayOfWeekString 'Thursday' @propHash | |
$friday = New-DayOfWeekString 'Friday' @propHash | |
$saturday = New-DayOfWeekString 'Saturday' @propHash | |
$sunday = New-DayOfWeekString 'Sunday' @propHash | |
$week = [Ordered] @{ | |
$tuesday = $null | |
$wednesday = $null | |
$thursday = $null | |
$friday = $null | |
$saturday = $null | |
} | |
if (($CultureInfo.DateTimeFormat.FirstDayOfWeek) -eq 'Monday') { | |
$week.Insert(0, $monday, $null) | |
$week.Add($sunday, $null) | |
} | |
else { | |
$week.Insert(0, $sunday, $null) | |
$week.Insert(1, $monday, $null) | |
} | |
Write-Output $week | |
} | |
# get a CultureInfo object based on user input | |
# either with an Invariant Culture... | |
if ($InvariantCulture) { | |
$cultureInfo = [System.Globalization.CultureInfo]::InvariantCulture | |
} | |
# ... user defined culture... | |
elseif ($Culture) { | |
$cultureInfo = [System.Globalization.CultureInfo]::CreateSpecificCulture($Culture) | |
} | |
# ... or the current culture | |
else { | |
$cultureInfo = [System.Globalization.CultureInfo]::CurrentCulture | |
} | |
# supporting internationalization | |
# add additional languages as needed | |
switch ($cultureInfo.Name) { | |
'nb-NO' {$translate = @{Year = 'År'; Month = 'Måned'; Week = 'Uke'}} # Norwegian (Bokmål) | |
'da-DK' {$translate = @{Year = 'År'; Month = 'Måned'; Week = 'Uge'}} # Danish | |
'sv-SE' {$translate = @{Year = 'År'; Month = 'Månad'; Week = 'Vecka'}} # Swedish | |
'fi-FI' {$translate = @{Year = 'Vuosi'; Month = 'Kuukausi'; Week = 'Viikko'}} # Finnish | |
'de-DE' {$translate = @{Year = 'Jahr'; Month = 'Monat'; Week = 'Woche'}} # German | |
'de-AT' {$translate = @{Year = 'Jahr'; Month = 'Monat'; Week = 'Woche'}} # German (Austria) | |
'de-CH' {$translate = @{Year = 'Jahr'; Month = 'Monat'; Week = 'Woche'}} # German (Switzerland) | |
'nl-NL' {$translate = @{Year = 'Jaar'; Month = 'Maand'; Week = 'Week'}} # Dutch | |
'fr-FR' {$translate = @{Year = 'Année'; Month = 'Mois'; Week = 'Semaine'}} # French | |
'fr-CH' {$translate = @{Year = 'Année'; Month = 'Mois'; Week = 'Semaine'}} # French (Switzerland) | |
'fr-LU' {$translate = @{Year = 'Année'; Month = 'Mois'; Week = 'Semaine'}} # French (Luxembourg) | |
'it-IT' {$translate = @{Year = 'Anno'; Month = 'Mese'; Week = 'Settimana'}} # Italian | |
'es-ES' {$translate = @{Year = 'Año'; Month = 'Mes'; Week = 'Semana'}} # Spanish | |
'ru-RU' {$translate = @{Year = 'Год'; Month = 'Месяц'; Week = 'Неделя'}} # Russian | |
'cs-CZ' {$translate = @{Year = 'Rok'; Month = 'Měsíc'; Week = 'Týden'}} # Czech | |
'ms-MY' {$translate = @{Year = 'Tahun'; Month = 'Bulan'; Week = 'Minggu'}} # Malay | |
'ja-JP' {$translate = @{Year = '年'; Month = '月'; Week = '1週間'}} # Japanese | |
'is-IS' {$translate = @{Year = 'Ári'; Month = 'Mánuði'; Week = 'Viku'}} # Icelandic | |
'pl-PL' {$translate = @{Year = 'Rok'; Month = 'Miesiąc'; Week = 'Tydzień'}} # Polish | |
'cy-GB' {$translate = @{Year = 'Blwyddyn'; Month = 'Mis'; Week = 'Wythnos'}} # Welsh (United Kingdom) | |
DEFAULT {$translate = @{Year = 'Year'; Month = 'Month'; Week = 'Week'}} # Invariant Culture (English) | |
} | |
$thisMonth = $StartMonth - 1 | |
$thisYear = $StartYear | |
$output = @() | |
$weekProperties = @{} | |
if ($AbbreviatedDayNames) { $weekProperties.Abbreviated = $true } | |
# loop through the months | |
for ($i = 1; $i -le $Months; $i++) { | |
# increment month | |
$thisMonth++ | |
# when month is greater than 12, a new year is triggered, so reset month to 1 and increment year | |
if ($thisMonth -gt 12) { | |
$thisMonth = 1 | |
$thisYear++ | |
} | |
# get the number of days in the month | |
$daysInMonth = $cultureInfo.Calendar.GetDaysInMonth($thisYear,$thisMonth) | |
# define new week | |
$thisWeek = $cultureInfo | New-Week @weekProperties | |
$thisWeek.Insert(0, $translate.Month, $null) | |
$thisWeek.Insert(1, $translate.Year, $null) | |
$thisWeek.Insert(2, $translate.Week, $null) | |
# loop through each day in the month | |
for ($y = 1; $y -lt ($daysInMonth + 1); $y++) { | |
# get a datetime object of the current date | |
$thisDate = New-Object -TypeName 'System.DateTime' -ArgumentList ($thisYear,$thisMonth,$y,$cultureInfo.Calendar) | |
# if current date is the first day of a week (but not if it's the very first day of the month at the same time) | |
if (($thisDate.DayOfWeek -eq ($cultureInfo.DateTimeFormat.FirstDayOfWeek)) -and ($y -gt 1)) { | |
# add the week object to the output array | |
$weekObject = New-Object -TypeName 'PSCustomObject' -Property $thisWeek | |
$output += $weekObject | |
# reset the week | |
$thisWeek = $cultureInfo | New-Week @weekProperties | |
$thisWeek.Insert(0, $translate.Month, $null) | |
$thisWeek.Insert(1, $translate.Year, $null) | |
$thisWeek.Insert(2, $translate.Week, $null) | |
} | |
# get string representation of the month and the current week number (if week number is 53, change to 1) | |
$monthString = $cultureInfo.TextInfo.ToTitleCase($thisDate.ToString('MMMM',$cultureInfo)) | |
$thisWeekNumber = $cultureInfo.calendar.GetWeekOfYear($thisDate,$cultureInfo.DateTimeFormat.CalendarWeekRule,$cultureInfo.DateTimeFormat.FirstDayOfWeek) | |
if ($thisWeekNumber -eq 53) { $thisWeekNumber = 1 } | |
# overload the ToString method of the datetime object | |
$thisDate | Add-Member -MemberType ScriptMethod -Name 'ToString' -Value { | |
# mark today with '*' | |
if (($this.Date) -eq ([DateTime]::Now.Date)) { | |
if($Alignment -eq 'Left') {$this.Day.ToString() + '*'} | |
else {'*' + $this.Day.ToString()} | |
} | |
elseif ($MarkDay -eq $this.Day) { | |
if($Alignment -eq 'Left') {$this.Day.ToString() + '!'} | |
else {'!' + $this.Day.ToString()} | |
} | |
elseif ($MarkDate.Date -eq $this.Date) { | |
if($Alignment -eq 'Left') {$this.Day.ToString() + '!'} | |
else {'!' + $this.Day.ToString()} | |
} | |
else { | |
$this.Day.ToString() | |
} | |
} -Force | |
# update the week hashtable with the current day, week, month and year | |
$thisWeek[($cultureInfo | New-DayOfWeekString ($thisDate.DayOfWeek) -Abbreviated:$AbbreviatedDayNames)] = $thisDate | |
$thisWeek[$translate.Week] = $thisWeekNumber | |
$thisWeek[$translate.Month] = $monthString | |
$thisWeek[$translate.Year] = $thisYear | |
} | |
# add the final week to the output array | |
$weekObject = New-Object -TypeName 'PSCustomObject' -Property $thisWeek | |
$output += $weekObject | |
} | |
# translate day names | |
$monday = $cultureInfo | New-DayOfWeekString 'Monday' -Abbreviated:$AbbreviatedDayNames | |
$tuesday = $cultureInfo | New-DayOfWeekString 'Tuesday' -Abbreviated:$AbbreviatedDayNames | |
$wednesday = $cultureInfo | New-DayOfWeekString 'Wednesday' -Abbreviated:$AbbreviatedDayNames | |
$thursday = $cultureInfo | New-DayOfWeekString 'Thursday' -Abbreviated:$AbbreviatedDayNames | |
$friday = $cultureInfo | New-DayOfWeekString 'Friday' -Abbreviated:$AbbreviatedDayNames | |
$saturday = $cultureInfo | New-DayOfWeekString 'Saturday' -Abbreviated:$AbbreviatedDayNames | |
$sunday = $cultureInfo | New-DayOfWeekString 'Sunday' -Abbreviated:$AbbreviatedDayNames | |
# define a hashtable to hold format properties for the table output | |
if (($cultureInfo.DateTimeFormat.FirstDayOfWeek) -eq 'Monday') { | |
$formatProperties = @{ | |
Property = | |
"$($translate.Week)", | |
@{Name = "$monday" ;Expression = {$_.$monday} ;Alignment = $Alignment}, | |
@{Name = "$tuesday" ;Expression = {$_.$tuesday} ;Alignment = $Alignment}, | |
@{Name = "$wednesday" ;Expression = {$_.$wednesday} ;Alignment = $Alignment}, | |
@{Name = "$thursday" ;Expression = {$_.$thursday} ;Alignment = $Alignment}, | |
@{Name = "$friday" ;Expression = {$_.$friday} ;Alignment = $Alignment}, | |
@{Name = "$saturday" ;Expression = {$_.$saturday} ;Alignment = $Alignment}, | |
@{Name = "$sunday" ;Expression = {$_.$sunday} ;Alignment = $Alignment} | |
} | |
} | |
else { | |
$formatProperties = @{ | |
Property = | |
"$($translate.Week)", | |
@{Name = "$sunday" ;Expression = {$_.$sunday} ;Alignment = $Alignment}, | |
@{Name = "$monday" ;Expression = {$_.$monday} ;Alignment = $Alignment}, | |
@{Name = "$tuesday" ;Expression = {$_.$tuesday} ;Alignment = $Alignment}, | |
@{Name = "$wednesday" ;Expression = {$_.$wednesday} ;Alignment = $Alignment}, | |
@{Name = "$thursday" ;Expression = {$_.$thursday} ;Alignment = $Alignment}, | |
@{Name = "$friday" ;Expression = {$_.$friday} ;Alignment = $Alignment}, | |
@{Name = "$saturday" ;Expression = {$_.$saturday} ;Alignment = $Alignment} | |
} | |
} | |
# if FormatPx is loaded, use it to format the output | |
if (Get-Module -Name 'FormatPx') { | |
Write-Output ($output | Format-Table @formatProperties -AutoSize -GroupBy @{Name = "$($translate.Month)";Expression = {"$($_.($translate.Month)) $($_.($translate.Year))"}} -PersistWhenOutput) | |
} | |
# else use default PowerShell formatting | |
else { | |
Write-Output ($output | Format-Table @formatProperties -AutoSize -GroupBy @{Name = "$($translate.Month)";Expression = {"$($_.($translate.Month)) $($_.($translate.Year))"}}) | |
} | |
} | |
New-Alias -Name 'cal' -Value 'Show-Calendar' -Force |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
nice one! any chance you update it, so multiple dates can be marked?