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().FullName
Expect 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().Name
Int32
Double
Decimal
Arithmetic 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.24
This 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
True
The 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.TotalSeconds
For 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.UtcDateTime
Use 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-List
This 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, TypeNameOfValue
Verification 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.