Numbers, Booleans, Date/Time, Type Conversion, and Type Accelerators
Understand PowerShell and .NET types through observable behavior, convert raw configuration strings safely, work with dates and durations, and make culture-sensitive boundaries explicit.
Learning objectives
- Describe the practical relationship between PowerShell values and .NET types without requiring C# knowledge.
- Work with integers, floating-point/decimal values, Booleans, DateTime/DateTimeOffset, and TimeSpan.
- Use common type accelerators and understand the difference between unconstrained and type-constrained variables.
- Distinguish implicit conversion from explicit conversion and diagnose conversion failures.
- Use PowerShell KB/MB/GB binary multipliers correctly in practical DevOps calculations.
- Parse machine-facing dates/numbers with explicit culture rules and produce validated typed configuration.
1. Types describe what a value can represent and do
PowerShell runs on .NET, a software platform that defines many reusable types. You do not need C# knowledge to use them. A type is the category and behavior of a value: an integer can participate in arithmetic, a date knows how to add days, and a version knows how to compare version components. PowerShell usually chooses a sensible type for literals and command output, then lets you inspect it when behavior matters.
42 | ForEach-Object { $_.GetType().FullName }
3.14 | ForEach-Object { $_.GetType().FullName }
(Get-Date).GetType().FullNameExpect System.Int32 for a small integer, System.Double for an ordinary real literal, and System.DateTime from Get-Date. The short PowerShell forms [int], [double], and [datetime] are type accelerators—convenient names for commonly used .NET types.
2. Numeric types carry different range and precision tradeoffs
For most counters, ports, retry counts, and exit codes, an integer is appropriate. Measurements can require fractional values. PowerShell ordinarily creates a Double for a literal such as 0.75. The Decimal type can be useful when decimal precision is important, such as financial calculations, but it is not automatically “better” for every measurement.
$replicas = 4
$cpuRatio = 0.625
$budget = 19.95d
$replicas.GetType().Name
$cpuRatio.GetType().Name
$budget.GetType().NameInt32
Double
DecimalArithmetic can change the result type. For example, dividing two integers can produce a Double when a fractional result is required. Inspect the result instead of assuming it retained the operand type.
3. KB, MB, and GB are binary multipliers in PowerShell numeric literals
PowerShell provides multiplier suffixes useful for file and memory calculations. In numeric literals, 1KB is 1024 bytes, 1MB is 1024² bytes, and 1GB is 1024³ bytes. Microsoft’s documentation names these kibibyte/mebibyte/gibibyte multipliers even though the suffix spelling is KB/MB/GB.
$artifactBytes = 750MB
$limitBytes = 1GB
$percentUsed = ($artifactBytes / $limitBytes) * 100
[math]::Round($percentUsed, 2)73.24This is convenient for local calculations, but be careful when an external API uses decimal units where “GB” means one billion bytes. Normalize units at the boundary and document the convention.
4. Booleans model yes/no state, but conversion has rules
The Boolean type has two values: $true and $false. Comparisons return Booleans, and conditional statements convert their conditions to Boolean values. Explicit conversion is worth learning because configuration strings can be misleading.
[bool]0
[bool]1
[bool]''
[bool]'false'False
True
False
TrueThe last result surprises beginners: any non-empty ordinary string is truthy, even the text "false". Therefore, do not validate a string configuration flag with [bool]$rawText. Parse expected textual values explicitly, for example with a small allow-list or [bool]::Parse() when the input is guaranteed to be True/False.
5. DateTime and TimeSpan let you model time instead of formatting strings
A date/time value should remain a date/time object while you compare, add, subtract, or sort it. A TimeSpan represents a duration. Converting these values to strings too early throws away useful operations and can introduce culture ambiguity.
$started = Get-Date
$deadline = $started.AddMinutes(15)
$duration = $deadline - $started
$started.GetType().Name
$duration.GetType().Name
$duration.TotalSecondsFor machine-to-machine timestamps, ISO 8601 and DateTimeOffset are often clearer because the offset is explicit. For example:
$stamp = [datetimeoffset]::Parse(
'2026-08-11T05:30:00Z',
[cultureinfo]::InvariantCulture
)
$stamp.UtcDateTimeUse the type to carry time semantics, then choose a string format only at an output boundary such as JSON, a log line, or a report.
6. Type accelerators are concise names for useful .NET types
| Accelerator | Represents | Practical use |
|---|---|---|
[int] | 32-bit signed integer | Retry counts, ports, small counters. |
[long] / [int64] | 64-bit signed integer | Large byte counts and IDs. |
[double] | Double-precision floating point | Measurements and ratios. |
[decimal] | Base-10 decimal | Values needing decimal precision. |
[bool] | Boolean | Validated yes/no state. |
[datetime] | Date and time | Timestamps and scheduling. |
[timespan] | Duration | Timeouts and elapsed time. |
[version] | Version components | Compare tool/runtime versions. |
[uri] | Uniform Resource Identifier | Validate/represent URLs and endpoints. |
[cultureinfo] | Culture rules | Explicit parsing/formatting behavior. |
A type literal can be used for explicit conversion—[int]'42'—or to constrain a variable—[int]$workers = 4. A constrained variable asks PowerShell to convert future assignments to that type or fail if conversion is impossible. Use constraints when the invariant improves correctness, not merely to make code look more formal.
7. Implicit conversion is convenient; explicit conversion makes boundaries obvious
PowerShell performs implicit conversion in many contexts, including parameter binding, type-constrained variables, and expressions. This flexibility is useful at the prompt but can hide invalid configuration. When reading external strings, explicit conversion makes the contract visible.
$rawWorkers = '6'
$workers = [int]$rawWorkers
$workers.GetType().Name
try {
[int]'six'
}
catch {
$_.Exception.Message
}The first conversion succeeds because "6" represents an integer. The second throws a conversion error. Production code should catch or validate boundary failures and report which setting was invalid rather than allowing a confusing downstream error.
8. Culture matters when text is converted to dates or numbers
A culture defines conventions such as decimal separators and date ordering. The text 01/02/2026 can be interpreted as January 2 or February 1 depending on culture. PowerShell’s conversion behavior is not uniformly culture-sensitive in every context: documented language conversion often uses invariant culture, while some cmdlet parameter binding is culture-sensitive. Do not rely on an implicit convention for machine configuration.
$culture = [cultureinfo]::InvariantCulture
$date = [datetime]::ParseExact('2026-08-11', 'yyyy-MM-dd', $culture)
$ratio = [double]::Parse('0.625', $culture)
$date.ToString('yyyy-MM-dd', $culture)
$ratio.ToString('0.000', $culture)For machine interfaces, prefer explicit, stable formats and invariant culture. For human-facing reports, the user’s culture may be exactly what you want. The key is deciding intentionally.
9. Turn raw configuration strings into typed state once
Environment variables, command-line arguments, and many configuration formats begin as text. Normalize them close to the boundary so the rest of your script can reason about types instead of repeatedly parsing strings.
$raw = [pscustomobject]@{
Workers = '4'
TimeoutSeconds = '30'
Enabled = 'true'
ArtifactLimit = '1073741824'
ReleaseDate = '2026-08-11'
}
try {
$typed = [pscustomobject]@{
Workers = [int]$raw.Workers
Timeout = [timespan]::FromSeconds([double]$raw.TimeoutSeconds)
Enabled = [bool]::Parse($raw.Enabled)
ArtifactLimitBytes = [long]$raw.ArtifactLimit
ReleaseDate = [datetime]::ParseExact(
$raw.ReleaseDate,
'yyyy-MM-dd',
[cultureinfo]::InvariantCulture
)
}
}
catch {
throw "Configuration conversion failed: $($_.Exception.Message)"
}
$typed | Format-ListThis pattern creates a useful boundary: before conversion, values are untrusted strings; after successful conversion, downstream logic receives typed values. Chapters 08 and 10 add parameter validation and richer error design.
10. Common conversion failures reveal an invalid contract
# Invalid integer
[int]'4.5'
# Invalid Boolean text for Boolean.Parse
[bool]::Parse('yes')
# Ambiguous date: avoid this in machine configuration
[datetime]'01/02/2026'The first two examples are intentionally wrong. The date example may succeed, but its interpretation can be unclear to readers and can depend on conversion context. A successful conversion is not automatically a safe contract. Prefer explicit formats that communicate intent to humans and machines.
11. Lab: validate typed deployment settings
Start with a set of raw strings that resemble values from environment variables or a CI system. Convert them, apply range checks, calculate a deadline and storage utilization, and inspect the final types.
$rawWorkers = '5'
$rawTimeoutSeconds = '45'
$rawEnabled = 'true'
$rawArtifactBytes = '786432000'
$rawWindowStart = '2026-08-11T05:30:00Z'
$workers = [int]$rawWorkers
$timeoutSeconds = [int]$rawTimeoutSeconds
$enabled = [bool]::Parse($rawEnabled)
$artifactBytes = [long]$rawArtifactBytes
$windowStart = [datetimeoffset]::Parse(
$rawWindowStart,
[cultureinfo]::InvariantCulture
)
if ($workers -lt 1 -or $workers -gt 50) {
throw 'Workers must be between 1 and 50.'
}
if ($timeoutSeconds -lt 1 -or $timeoutSeconds -gt 600) {
throw 'TimeoutSeconds must be between 1 and 600.'
}
$deadline = $windowStart.AddSeconds($timeoutSeconds)
$limit = 1GB
$utilization = [math]::Round(($artifactBytes / $limit) * 100, 2)
$settings = [pscustomobject]@{
Workers = $workers
Enabled = $enabled
Timeout = [timespan]::FromSeconds($timeoutSeconds)
ArtifactBytes = $artifactBytes
ArtifactUtilizationPercent = $utilization
WindowStart = $windowStart
Deadline = $deadline
}
$settings | Format-List
$settings.PSObject.Properties | Select-Object Name, TypeNameOfValueVerification checklist
12. Knowledge check
Question 1. What type does PowerShell normally assign to the literal 3.14?
3.14 is normally a System.Double.Question 2. Why does [bool]'false' produce True?
Question 3. How many bytes does 1MB represent in a PowerShell numeric literal?
Question 4. Why keep a timestamp as DateTime/DateTimeOffset instead of immediately formatting it as text?
Question 5. When should invariant culture be preferred?
13. Summary
PowerShell values are typed .NET objects even when the language lets you write code without explicit declarations. Integers, floating-point values, decimals, Booleans, dates, durations, versions, and URIs have different behavior because their types model different domains. External configuration often arrives as text; convert and validate it once at the boundary, use explicit culture rules for machine formats, and retain rich types until a real serialization or display boundary.
14. Further reading
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this address.