Reputation: 2183
As I have mentioned in the Question title, I want to convert the ConvertFrom-Json
command's output to string such that, the character/string I get, should be usable such that it can be inserted into DateTime string as replacement to another character.
Currently I have following code to get the present DateTime:
$DTCurr = (Get-Date).tostring("dd-MM-yyyy_hh+mm+ss")
Now in the above code, I want to force replace the plus sign with colon sign, such that the resulting DateTime string can be used in the file-naming, so I am expecting the output(after replacement) like below:
07-11-2020_12:59:13
Now I tried this code for that forced replacement, but it doesn't work:
$colon = ('{ "str": "\uA789" }' | ConvertFrom-Json)
$DTCurr = (Get-Date).tostring("dd-MM-yyyy_hh+mm+ss")
$DTCurr = $DTCurr -replace "\+",$colon
Echo $DTCurr
This gives the output: 07-11-2020_02@{str=꞉}06@{str=꞉}28
which is ridiculous and unexpected. I can assure that $colon
does print :
when passed to Echo
.
Can someone let me know what I doing wrong and help out achieve this ?
Upvotes: 1
Views: 398
Reputation: 439487
PowerShellGuy's helpful answer solves your problem; let me complement it:
tl;dr
# Use a [char] cast with the Unicode code point to create the char.
# of interest - no need for using JSON for that.
PS> (Get-Date).ToString('dd-MM-yyyy_hh+mm+ss') -replace '\+', [char] 0xA789
06-11-2020_09꞉17꞉25
It seems that the sole reason you're using a JSON representation is to get a string with a Unicode character beyond the ANSI/ASCII-range, namely ꞉
(MODIFIER LETTER COLON, U+A789
), which looks just like the ASCII-range :
(COLON, U+003A
), but isn't.
If we assume that you need this JSON detour - which you don't - the simplest solution would have been:
$colonSubstitute = '"\uA789"' | ConvertFrom-Json
The JSON detour isn't needed, because you can cast Unicode code points directly to [char]
(System.Char
):
# Directly creates Unicode char. U+A789 as a [char] (System.Char) instance.
$colonSubstitute = [char] 0xA789
You could cast that to a [string]
instance, though that is often not necessary, given PowerShell's automatic, flexible type conversions (see below):
$colonSubstitute = [string] [char] 0xA789
PowerShell [Core] v6+ directly supports Unicode escape sequences (akin to JSON's) inside double-quoted strings ("..."
), also known as expandable (interpolating) strings, using the syntax `u{n}
, where n
is the character's Unicode code point:
# PowerShell [Core] v6+ escape sequence
# Same as: "$([char] 0xA789)"
$colonSubstitute = "`u{A789}"
Note: Unlike [char]
casts, the `u{n}
syntax also supports characters beyond the Unicode BMP (Basic Multilingual Plane), i.e., characters with code points greater than U+FFFF
(0xFFFF
); e.g., "`u{1F913}"
for 🤓
. However, in the resulting (expanded) string such characters are represented as two [char]
(System.Char
) instances, so-called surrogate pairs, because .NET characters are UTF-16, i.e. 16-bit code units with a max. value of 0xFFFF
and therefore cannot directly represent non-BMP characters; thus, for instance, "`u{1F913}".Length
yields 2
.
In Windows PowerShell, you can use $(...)
, the subexpression operator, to embed [char]
casts inside double-quoted strings ("..."
):
$colonSubstitute = "$([char] 0xA789)"
Note: As discussed, [char]
(System.Char
) casts are limited to characters in the Unicode BMP. While characters in the non-BMP range (code points 0x10000
and up) are rare overall, you do need them for emoji, such as 🤓
(NERD FACE , U+1F913).
Unlike the PowerShell [Core] v6+ syntax, using [char]
casts to represent surrogate pairs is neither obvious nor convenient:
For instance, to represent 🤓
, you must (a) know that non-BMP code point U+1F913
is represented as UTF-16 surrogate pair 0xD83E
, 0xDD13
, and then embed the latter in either of these two forms:
"$(-join [char[]] (0xD83E, 0xDD13))"
or "$([char] 0xD83E)$([char] 0xDD13)"
Finally, given PowerShell's automatic, flexible type conversions, you can directly use a [char]
instance as the operands of the -replace
operator:
PS> (Get-Date).ToString('dd-MM-yyyy_hh+mm+ss') -replace '\+', [char] 0xA789
06-11-2020_09꞉17꞉25
Upvotes: 1
Reputation: 801
Sorry if I'm misconstruing this, but I think your end goal can be simplified by doing this
$DTCurr = (Get-Date).tostring("dd-MM-yyyy_hh:mm:ss")
or this
$DTCurr = (Get-Date).tostring("dd-MM-yyyy_hh+mm+ss")
$colonDT = $DTCurr -replace "\+",":"
but if you wanna do it your way, the reason why it's printing that output, is because it's doing exactly what you're telling it to do. You're replacing the +
with an object that has a property named str
with a value of :
. You would need to do this instead
$colon = ('{ "str": "\uA789" }' | ConvertFrom-Json)
$DTCurr = (Get-Date).tostring("dd-MM-yyyy_hh+mm+ss")
$colonDT = $DTCurr -replace "\+",$colon.str
Echo $colonDT
If I am incorrect, and you need more assistance, let me know.
Upvotes: 2