1

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)
dwids
  • 67
  • 2
  • 7
  • please show a [mcve]. Did you use `ConvertFrom-Json`? And why do you match dates as strings instead of doing a proper comparison? – phuclv Jun 12 '22 at 08:49
  • Thanks. Yes I did use `ConvertFrom-Json`. I'm still fairly new to PowerShell, so what do you mean by 'proper comparison'? I'm trying to learn how to search for all objects/records that have a date of '2012-11' (i.e. all of November 2021) or those with '2012-11-10' etc. FYI the source data is Google Takeout Location (JSON). – dwids Jun 12 '22 at 10:21
  • 1
    I mean the [`[datetime]` type](https://learn.microsoft.com/en-us/dotnet/api/system.datetime?view=net-6.0) already has comparison operators so just compare it like `$data |% { $_.DTSlocal -eq [datetime]::new(2022, 6, 12)`. Anyway please make a [mcve] to make the question valid – phuclv Jun 12 '22 at 10:28

2 Answers2

1

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 on how ConvertFrom-Json parses dates, 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.
    • PowerShell requests use of this invariant culture from (non-string) objects by passing [cultureinfo]::InvariantCulture, which implements the System.IFormatProvider interface, to the System.IFormatProvider-typed provider or formatProvider 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 the IFormattable interface.
      • The target object's .ToString method, if it has an overload that accepts an IFormatProvider 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.

mklement0
  • 382,024
  • 64
  • 607
  • 775
0

.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
js2010
  • 23,033
  • 6
  • 64
  • 66
  • Yes, argument-less `.ToString()` calls on .NET types that support culture-sensitive representations _do_ return representations based on the _current culture_ - but that is precisely why you shouldn't use them: not only is the result dependent on what the current culture is - and may therefore act differently on other machines - .NET cultures are permitted to change over time (although that happens only infrequently). PowerShell's implicit use of the _invariant culture_ is something to embrace for programmatic processing with long-term stability. – mklement0 Jun 12 '22 at 21:28
  • 1
    Of course, it's even better to avoid working with _string representations_ of (non-string) data altogether, when possible. – mklement0 Jun 12 '22 at 21:28
  • 1
    Thank you again to those who have not only responded, but taken the time to explain - n some detail - specifically @mklement0 I'm not a developer but like to learn such things to solve problems like "I've got a huge Google Takeout Location Json export file. Where was I on 10th November 2012? Or when did I visit Melbourne? " I can use Geolocation APIs already, from an earlier photo-location exercise. – dwids Jun 13 '22 at 23:36