I've got my dates in a JSON file in sortable (-s). The first is:
"DTSlocal": "2012-11-10T08:09:35"
This is 10th November 2012 at 08:09:35 (local)
When I load the file and convert from JSON (new object = $data), PowerShell tells me the above sample value is now:
$data[0].DTSlocal
Saturday, 10 November 2012 8:09:35 AM
Ok, good. But, to find ALL the data from this date I've tried:
$data | Where-Object -Property DTSlocal -LIKE '10/11/2012*' #fails
$data | Where-Object -Property DTSlocal -LIKE '11/10/2012*' #works (!)
My Culture values are correctly set for 'Australia', viz d-MM-yyyy etc
Am I doing something wrong in having to search in 'American' format?
Update 01: Add example, as requested. Note: this is how I was trying it rather than using the subsequent suggestions. So others can learn what was going wrong. I'll also try the suggestions and report back.
Sample data file 'tinySample.json':
[
{
"DTSorig": "2012-11-09T21:09:35.612Z",
"DTSlocal": "2012-11-10T08:09:35",
"Latitude": -39.9526772,
"Longitude": 146.8924461,
"Source": "WIFI",
"Accuracy": 24
},
{
"DTSorig": "2012-11-09T21:11:32.285Z",
"DTSlocal": "2012-11-10T08:11:32",
"Latitude": -36.8526774,
"Longitude": 142.8924487,
"Source": "WIFI",
"Accuracy": 23
}
]
Powershell testing:
$data = Get-Content .\tinySample.json | ConvertFrom-Json
# quick look at PS object's values:
$data
DTSorig : 9/11/2012 9:09:35 PM
DTSlocal : 10/11/2012 8:09:35 AM
Latitude : -39.9526772
Longitude : 146.8924461
Source : WIFI
Accuracy : 24
DTSorig : 9/11/2012 9:11:32 PM
DTSlocal : 10/11/2012 8:11:32 AM
Latitude : -36.8526774
Longitude : 142.8924487
Source : WIFI
Accuracy : 23
# Find values for 10th November 2012
$data | Where-Object -Property DTSlocal -LIKE '10/11/2012*'
#nothing
$data | Where-Object -Property DTSlocal -LIKE '11/10/2012*'
# same two values returned as per $data (above)
CodePudding user response:
ConvertFrom-Json
in PowerShell (Core) 7 implicitly converts string JSON property values such as "2012-11-10T08:09:35"
to [datetime]
instances, so that is what your -like
operation operates on - see this answer for more information, including how things work differently in Windows PowerShell.
-like
is a string operator, which, as all PowerShell string operators do, implicitly stringifies its LHS, if it isn't already a string.PowerShell typically stringifies in a culture-invariant manner; specifically, it uses the so-called invariant culture,
[cultureinfo]::InvariantCulture
(System.Globalization.CultureInfo.InvariantCulture
), which is a culture based on the US English culture, but distinct from it and guaranteed not to change over time.It is these qualities - culture-independence, long-term stability - that make the invariant culture suitable for programmatic processing, whereas culture-sensitive representations not only depend on the runtime environment but are permitted to change over time.
- Argument-less
.ToString()
calls on .NET types that support culture-sensitive representations do return such culture-dependent representations, which is why you should not rely on them in programmatic processing.
- Argument-less
PowerShell requests use of this invariant culture from (non-string) objects by passing
[cultureinfo]::InvariantCulture
, which implements theSystem.IFormatProvider
interface, to theSystem.IFormatProvider
-typedprovider
orformatProvider
argument of one of the following, in order of precedence, if available (not all .NET types support culture-appropriate representations):System.IFormattable.ToString
, if the target object's type supports theIFormattable
interface.- The target object's
.ToString
method, if it has an overload that accepts anIFormatProvider
as the only parameter.
Since the invariant culture is based on the US English culture, it uses a month-first format in short, numeric date representations, such as when you stringify a [datetime]
(System.DateTime
) instance.
Applied to a simplified example:
[datetime] "2012-11-10T08:09:35" -like '11/10/2012*'
is implicitly the same as:
([System.IFormattable] [datetime] "2012-11-10T08:09:35").
ToString(
[NullString]::Value,
[System.IFormatProvider] [cultureinfo]::InvariantCulture
) -like '11/10/2012*'
which is implicitly the same as:
'11/10/2012 08:09:35' -like '11/10/2012*'
and therefore $true
.
As phuclv points out, however, it's worth considering working with the properties and methods of the [datetime]
(System.DateTime
) type directly, instead of relying on string representations.
CodePudding user response:
.tostring() seems to do what you want vs the implied conversion.
set-culture en-au # then restart powershell
$a = get-date
"$a"
06/12/2022 13:19:46
$a.tostring()
12/06/2022 1:19:46 PM
$a.tostring() -like '12/06/2022*'
True
set-culture en-us