Skip to content

Instantly share code, notes, and snippets.

@thedavecarroll
Last active January 10, 2023 23:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save thedavecarroll/458429ec442b109ea8d6ba46b9ed7b18 to your computer and use it in GitHub Desktop.
Save thedavecarroll/458429ec442b109ea8d6ba46b9ed7b18 to your computer and use it in GitHub Desktop.
IronScripter Challenge - November 15, 2019 - Beginner PowerShell Function
function ConvertTo-Celsius {
param($Fahrenheit)
($Fahrenheit - 32) * 5/9
}
function ConvertTo-Fahrenheit {
param($Celsius)
($Celsius * 9/5) + 32
}
function ConvertTo-Celsius {
param($Fahrenheit)
process {
[PsCustomObject]@{
Fahrenheit = $Fahrenheit
Celsius = ($Fahrenheit - 32) * 5/9
}
}
}
function ConvertTo-Fahrenheit {
param($Celsius)
process {
[PsCustomObject]@{
Celsius = $Celsius
Fahrenheit = ($Celsius * 9/5) + 32
}
}
}
function ConvertTo-Celsius {
param(
[Parameter(ValueFromPipeline,Position=0)]
[decimal[]]$Fahrenheit,
[ValidateRange(0,28)]
[int]$Precision = 1
)
process {
foreach ($Temperature in $Fahrenheit) {
if ($Temperature -ge -459.67) {
[PsCustomObject]@{
Fahrenheit = $Temperature
Celsius = [math]::Round(($Temperature - 32) * 5/9,$Precision)
}
} else {
'{0} {1}F is below absolute zero. Please try again.' -f $Temperature,[char]176 | Write-Warning
}
}
}
}
function ConvertTo-Fahrenheit {
param(
[Parameter(ValueFromPipeline,Position=0)]
[decimal[]]$Celsius,
[ValidateRange(0,28)]
[int]$Precision = 1
)
process {
foreach ($Temperature in $Celsius) {
if ($Temperature -ge -273.15) {
[PsCustomObject]@{
Celsius = $Temperature
Fahrenheit = [math]::Round(($Temperature * 9/5) + 32,$Precision)
}
} else {
'{0} {1}F is below absolute zero. Please try again.' -f $Temperature,[char]176 | Write-Warning
}
}
}
}
class Temperature {
[decimal]$Value
[ValidateSet('F','C','K')]
[string]$Unit
hidden [string]$Comment
Temperature () {}
Temperature ( $Value, $Unit) {
$BelowAbsoluteZero = switch ($Unit) {
'F' { if ($Value -lt -459.67) { $true } }
'C' { if ($Value -lt -273.15) { $true } }
'K' { if ($Value -lt 0) { $true } }
default { $false }
}
if ($BelowAbsoluteZero) {
if ($Unit -match 'F|C' ) {
throw ('{0} {1}{2} is below absolute zero. Please try again.' -f $Value,[char]176,$Unit)
} else {
throw ('{0} {1} is below absolute zero. Please try again.' -f $Value,$Unit)
}
}
$this.Unit = $Unit
$this.Value = $Value
$this.Comment = $this.GetStateChangeComment()
}
[string] ToString () {
if ($this.Unit -match 'F|C') {
return '{0} {1}{2}' -f $this.Value,[char]176,$this.Unit
} else {
return '{0} {1}' -f $this.Value,$this.Unit
}
}
[decimal] ToFahrenheit () {
$ToFahrenheit = switch ($this.Unit) {
'C' { ($this.Value * 9/5) + 32 }
'K' { ($this.Value - 273.15) * 9/5 + 32 }
default { $this.Value }
}
return $ToFahrenheit
}
[decimal] ToFahrenheit ([int]$Precision) {
$ToFahrenheit = switch ($this.Unit) {
'C' { ($this.Value * 9/5) + 32 }
'K' { ($this.Value - 273.15) * 9/5 + 32 }
default { $this.Value }
}
return [decimal]::Round($ToFahrenheit,$Precision)
}
[string] ToFahrenheitString () {
return '{0} {1}{2}' -f $this.ToFahrenheit(),[char]176,'F'
}
[string] ToFahrenheitString ([int]$Precision) {
return '{0} {1}{2}' -f $this.ToFahrenheit($Precision),[char]176,'F'
}
[decimal] ToCelsius () {
$ToCelsius = switch ($this.Unit) {
'F' { ($this.Value - 32) * 5/9 }
'K' { $this.Value - 273.15 }
default { $this.Value }
}
return $ToCelsius
}
[decimal] ToCelsius ([int]$Precision) {
$ToCelsius = switch ($this.Unit) {
'F' { ($this.Value - 32) * 5/9 }
'K' { $this.Value - 273.15 }
default { $this.Value }
}
return [decimal]::Round($ToCelsius,$Precision)
}
[string] ToCelsiusString () {
return '{0} {1}{2}' -f $this.ToCelsius(),[char]176,'C'
}
[string] ToCelsiusString ([int]$Precision) {
return '{0} {1}{2}' -f $this.ToCelsius($Precision),[char]176,'C'
}
[decimal] ToKelvin () {
$ToKelvin = switch ($this.Unit) {
'F' { ($this.Value - 32) * 5/9 + 273.15 }
'C' { $this.Value + 273.15 }
default { $this.Value }
}
return $ToKelvin
}
[decimal] ToKelvin ([int]$Precision) {
$ToKelvin = switch ($this.Unit) {
'F' { ($this.Value - 32) * 5/9 + 273.15 }
'C' { $this.Value + 273.15 }
default { $this.Value }
}
return [decimal]::Round($ToKelvin,$Precision)
}
[string] ToKelvinString () {
return '{0} {1}' -f $this.ToKelvin(),'K'
}
[string] ToKelvinString ([int]$Precision) {
return '{0} {1}' -f $this.ToKelvin($Precision),'K'
}
[object] Convert () {
return [PsCustomObject]@{
Fahrenheit = $this.ToFahrenheit()
Celsius = $this.ToCelsius()
Kelvin = $this.ToKelvin()
Comment = $this.Comment
}
}
[object] Convert ([int]$Precision) {
return [PsCustomObject]@{
Fahrenheit = $this.ToFahrenheit($Precision)
Celsius = $this.ToCelsius($Precision)
Kelvin = $this.ToKelvin($Precision)
Comment = $this.Comment
}
}
[object] ConvertWithString () {
return [PsCustomObject]@{
Fahrenheit = $this.ToFahrenheit()
FahrenheitString = $this.ToFahrenheitString()
Celsius = $this.ToCelsius()
CelsiusString = $this.ToCelsiusString()
Kelvin = $this.ToKelvin()
KelvinString = $this.ToKelvinString()
Comment = $this.Comment
}
}
[object] ConvertWithString ([int]$Precision) {
return [PsCustomObject]@{
Fahrenheit = $this.ToFahrenheit($Precision)
FahrenheitString = $this.ToFahrenheitString($Precision)
Celsius = $this.ToCelsius($Precision)
CelsiusString = $this.ToCelsiusString($Precision)
Kelvin = $this.ToKelvin($Precision)
KelvinString = $this.ToKelvinString($Precision)
Comment = $this.Comment
}
}
[string] GetStateChangeComment () {
if ($this.ToCelsius() -eq -273.15) {
$GetStateChangeComment = 'Absolute Zero'
} else {
$Celsius = $this.ToCelsius(0)
$GetStateChangeComment = switch ($Celsius) {
0 { 'Freezing Point' ; break }
3 { 'Near Freezing Point' ; break }
100 { 'Boiling Point' ; break }
233 { 'Fahrenheit 451 – the temperature at which book paper catches fire, and burns...' ; break }
5505 { 'Surface of the Sun' ; break }
}
}
return $GetStateChangeComment
}
}
@thedavecarroll
Copy link
Author

Beginner PowerShell Functions - Fahrenheit/Celsius Conversion

This gist is my response to the IronScripter Beginner PowerShell Function challenge.

Simple Functions

The first two functions assumes you will provide some form of number (integer, byte, decimal).

D:\> ConvertTo-Celsius -Fahrenheit 212
100
D:\> ConvertTo-Fahrenheit -Celsius 33
91.4

Intermediate Functions

The intermediate functions takes the supplied parameter and returns a PSCustomObject with two properties, one for the original temperature and another for the converted temperature.

In order to allow a negative number, the calculation converts the supplied temperature to a System.Decimal type.

D:\> ConvertTo-Celsius -Fahrenheit 9941

Fahrenheit Celsius
---------- -------
      9941    5505

D:\> ConvertTo-Fahrenheit -Celsius -273.15

Celsius Fahrenheit
------- ----------
-273.15    -459.67

Advanced Functions

The two advanced functions can take in an array of System.Decimal objects from the pipeline (or via the parameter) and allows the user to specify the precision (what decimal point to round to). Additionally, if the temperature provided is below absolute zero, a warning is generated. The functions returns an object for each valid temperature that has the original temperature and another for the converted temperature.

D:\> -459.68,0,32,212,451 | ConvertTo-Celsius -Precision 4
WARNING: -459.68 °F is below absolute zero. Please try again.

Fahrenheit  Celsius
----------  -------
         0 -17.7778
        32        0
       212      100
       451 232.7778

D:\> -273.15,0,100,180 | ConvertTo-Fahrenheit -Precision 4

Celsius Fahrenheit
------- ----------
-273.15    -459.67
      0         32
    100        212
    180        356

Temperature Class

Once I completed the three levels of functions, I wanted to create a PowerShell custom class, [Temperature].

The basic constructor requires two parameters, a [decimal] and a [string], which must be either 'C', 'F', or 'K' to signify a specific measurement unit.

D:\> [Temperature]::new(72,'F')

Value Unit
----- ----
   72 F

Methods

Within the class definition, several methods provides the user options for converting and displaying temperatures.

Method Purpose Overload
ToString() Returns a [string] of the value, unit, and the degree symbol (except for K) No
ToFahrenheit() Returns a [decimal] of the original value, converted to Fahrenheit [int] Precision
ToFahrenheitString() Returns a [string] of the value converted to Fahrenheit, unit, and the degree symbol [int] Precision
ToCelsius() Returns a [decimal] of the original value, converted to Celsius [int] Precision
ToCelsiusString() Returns a [string] of the value converted to Celsius, unit, and the degree symbol [int] Precision
ToKelvin() Returns a [decimal] of the original value, converted to Kelvin [int] Precision
ToKelvinString() Returns a [string] of the value converted to Kelvin and unit [int] Precision
Convert() Returns an [PSCustomObject] with the Fahrenheit, Celsius, Kelvin, and Comment [int] Precision
ConvertWithString() Returns an [PSCustomObject] with the Fahrenheit, Celsius, Kelvin, their string representations, and Comment [int] Precision
GetStateChangeComment() Returns a [string] describing the temperature, such as boiling point No

Description of the Temperature

The description of several significant points for the temperature are stored in the hidden Comment property.

D:\> $Degrees = [Temperature]::new(212,'F')
D:\> $Degrees | Select-Object Value,Unit,Comment

Value Unit Comment
----- ---- -------
  212 F    Boiling Point

You can also call the GetStateChangeComment() method to see the Comment.

D:\> [Temperature]::new(451,'F').GetStateChangeComment()
Fahrenheit 451 – the temperature at which book paper catches fire, and burns...

Multiple Conversions

You can call the ConvertWithString() method to see all of the temperatures with their string equivalents.

D:\GitHub> [Temperature]::new(9941,'F').ConvertWithString(3)

Fahrenheit       : 9941
FahrenheitString : 9941 °F
Celsius          : 5505
CelsiusString    : 5505 °C
Kelvin           : 5778.15
KelvinString     : 5778.15 K
Comment          : Surface of the Sun

By calling the ToCelsiusString() and ToFahrenheitString() methods inline, you could present the three temperatures at the same time.

D:\>  [Temperature]::new(212,'F') | Select-Object @{l='Fahrenheit';e={$_.ToString()}},@{l='Celsius';e={$_.ToCelsiusString()}},@{l='Kelvin';e={$_.ToKelvinString()}},Comment

Fahrenheit Celsius Kelvin   Comment
---------- ------- ------   -------
212 °F     100 °C  373.15 K Boiling Point

Summary

Temperature conversion is very common in getting someone familiar with new programming or scripting language. I remember doing something similar for Commodore 64 in the mid-80's.

I had fun building the PowerShell custom class and learned a few things along the way.

Please feel free to leave a comment.

@jdhitsolutions
Copy link

Catching a value below absolute zero is a great call. I wouldn't have thought of that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment