Powershell get-childitem で指定された最終更新日が指定された日時以降の表記  How to expression date time, ealier or later.

# なかなかない
これはネットにある情報を組み合わせてようやくできました。
今日から45日前などの例はあるのですが、指定された日付以降というのがありません。

# 組み合わせ

## 日付の表記

```powershell
[DateTime]"2021/05/25 23:50"
```

これも意外と見つからなかったのですが、Datetimeをつけるのがカギでした
これをキャスト（する）と言います。キャストを仮訳すると、「（型）指定（する）」という意味です。

### ParseExactも似ているが基本的に変換
他にParseExactもあります。これは日付の表記というよりは西暦を和暦に変換するという使い方です。あるいは292191911253といような連続する文字列を日時に変換するという場合です。第三員数は`$null`が一般的ですが、日本の場合は`ja-JP`です。
一般的には`[cultureinfo]::InvariantCulture`これでもあまり問題が起きません。細かく言うとめんどくさいです。
しかし`$null`で済ませることができるのでそいうのは活用しましょう。日本語の場合はシステムの設定が優先されて`ja-JP`が入力されたのと同じ効果があります。さきほどCastは「指定」と読み替えていいと申し上げましたが、「ParseExact」は「（もともと型指定されているか、または型指定可能な文字列の）変換」」を意味しているわけです。
今回のサンプルはCastを使います。

```powershell
[System.DateTime]::ParseExact("2021/01/01 11:22:33","ggyy/MM/dd hh:mm:ss", [cultureinfo]::"ja-JP")
[System.DateTime]::ParseExact("2021/01/01 11:22:33","yyyy/MM/dd hh:mm:ss", [cultureinfo]::InvariantCulture)
[System.DateTime]::ParseExact("2021/01/01 11:22:33","yyyy/MM/dd hh:mm:ss", Null)

```

[[Powershell]文字列を日付に変換する](https://sevenb.jp/wordpress/ura/2015/08/06/powershell%E6%96%87%E5%AD%97%E5%88%97%E3%82%92%E6%97%A5%E4%BB%98%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B/)

## 比較演算子
-le 以前
-ge 以後
もっともこの演算子は-gt -ltを使ってもあまり変わらない時があります。
重要なことは
***以降ならちょっと前、以前ならちょっと後***にする
ということです。
たとえば23：45分以降のファイルを取りたいときは
23：44にします
23：45以前のファイルにしたいときは
23：46にします
-ge -leなら23:45でいいじゃないか、と思うのですが、拾わない時があります。
この原因はPowershellの時刻の書式設定は秒以下の単位まで表示形式が定められています。
正確かはどうか別にして、Poweshellのカスタム日付書式には秒以下の設定があります。ということはエクスプローラーや、ファイルのプロパティで一見45秒と示されていても、実はシステムにとっては、45.01秒かもしれません。そうすると、「45秒以下」というときには45.01秒のタイムスタンプでは範囲外になります。カスタム書式設定から推定するとファイルのタイムスタンプは秒以下まで存在していることがわかりますつまり「45秒というのは「45.9999...」という場合があるので46で切るほうがいいということになります。

## Where-Objectを使う

```powershell
Where-Object{$_.LastWriteTime -gt [Datetime]"2017/03/28 23:44"}
```
get-childitemから日付で絞り込むときはパイプラインでWhere-Objectをつかう。これはわかるのですが、日付がこういう書き方になります。

##ワンライナー
###以降の場合
C:\hoge の最終更新日が2017年3月28日23時45分以降のファイルを表示するには
上記の通り23：44からとして $folderpath でフォルダー名を決めています
これは日付なら3/27に変えます

```powershell
$Folderpath = "C:\hoge";Get-ChildItem $Folderpath | Where-Object{$_.LastWriteTime -gt [Datetime]"2017/03/28 23:44"} | Sort-Object  LastWriteTime 
```
####日時も変数の以降のワンライナー
変数\$Dtに代入するとき[Datetime]$Dt="2017/03/28 23:44"
となります。


```powershell
$Folderpath = "F:\";[Datetime]$Dt="2017/03/28 23:44";Get-ChildItem $Folderpath | Where-Object{$_.LastWriteTime -gt $dt} | Sort-Object  LastWriteTime
```

###以前の場合
23：45以前のファイルを出します。
確実に引っ掛けるため23:46になっています。
これは日付なら3/29に変えます
####変数が以前のワンライナーはSortを逆にする
比較演算子が変わり、Sort-Objectにオプションが付きます

```powershell
$Folderpath = "F:\";[Datetime]$Dt="2017/03/28 23:46";Get-ChildItem $Folderpath | Where-Object{$_.LastWriteTime -lt $dt} | Sort-Object -Descending LastWriteTime 
```

####日時も変数の以降のワンライナー
変数\$Dtに代入するとき[Datetime]$Dt="2017/03/28 23:44"
となります。
また時間、比較演算子、ソート順を変えるのも同様です

```powershell
$Folderpath = "F:\";[Datetime]$Dt="2017/03/28 23:46";Get-ChildItem $Folderpath | Where-Object{$_.LastWriteTime -lt $dt} | Sort-Object -Descending LastWriteTime 
```

##Between
それでは指定された日時の以前、以後はできるのか？できます。
`Where-Object`の中身を

```Powershell
(-gt) -and (-lt)
```

とかっこで包んで-andで結びます。

###ワンライナー
2021年3月28日23時45分から2021年5月5日の間に更新されたファイルなら
最終日を5月6日00時00分より前として

```powershell
$Folderpath = "c:\hoge";Get-ChildItem $Folderpath | Where-Object{($_.LastWriteTime -gt [Datetime]"2021/03/28 23:44") -and ($_.LastWriteTime -lt [Datetime]"2021/05/06 00:00")} | Sort-Object  LastWriteTime
```

###スクリプト
最後はスクリプトにした方がわかりやすいですね

```powershell
# Set-ExecutionPolicy RemoteSigned -Scope Process -Force
#Start#
 $Folderpath = "C:\hoge" #検索するフォルダー
 [System.Datetime]$dtStart = "2021/03/28 23:44" #開始は少し少なく
 [System.Datetime]$dtEnd = "2021/05/06 00:00" #終端は少し大きく
 Get-ChildItem $Folderpath | Where-Object{
( #開始条件 かっこ注意                                           
  $_.LastWriteTime -gt $dtStart
  ) -and (                                   
  $_.LastWriteTime -lt $dtEnd
                            )#終端条件 かっこ注意
} |
 Sort-Object LastWriteTime #パイプライン'|'は上の行にすること(パイプラインが切れてエラーになる)
#End#

```