代码之家  ›  专栏  ›  技术社区  ›  Code Novice

如何在PowerShell日期变量中更新年份

  •  1
  • Code Novice  · 技术社区  · 1 年前

    如何只更新Powershell中现有日期变量的年份?我一直在尝试更新PowerShell日期变量的年份,但尚未成功。

    我尝试发布最小代码,根据一些答案,我发现我发布的代码太小了。我没有在任何地方的实际代码中使用GetDate。我有几个年份无效的日期,比如1058年,还有一些日期是1059年。这些都需要更新到有效年份,我选择将它们更新到1900年,但我不知道如何做到这一点。

    PS > $DateUpdateYear = Get-Date # This is actually a date in a csv file imported into PowerShell using Import-Csv.  I have 73k records and one column has bad dates.  I need to find these bad dates less than the year 1900 and update them to 1900.
    PS > $DateUpdateYear.Year
    output > 2023
    PS > $DateUpdateYear.Year = 1900
    output > InvalidOperation: 'Year' is a ReadOnly property
    

    每次我在谷歌上搜索如何设置年份时,我都会继续获得set-Date cmdlet的结果,每次我阅读set-Date的文档时,我没有看到任何关于设置现有日期的年份的信息。

    我决定尝试一种看起来“太好了,不可能是真的”的尝试,只需使用 $DateUpdateYear.Year = 1900 但是,当尝试执行此操作时,错误会指出属性为只读。

    TL;DR------------------------------------------------------------TL:DR

    此答案已成功回答,为了帮助任何其他可能希望在导入SQL Server(Express/AAzure)之前通过循环更新日期字符串的人,下面将向您展示如何实现这一点,并展示如何克服将数据导入SQL Server/AAzure的其他一些障碍。

    有三个主要问题需要克服,它们如下:

    1. 行尾字符是换行符。以新行作为行尾字符的导出文件在基于Linux的系统中是典型的。我发现很多工具都讨厌换行,所以Powershell脚本的第一步是将EOL换行替换为标准的回车换行。LF->CRLF
    2. 下一个问题是,导入的文件需要一个列来表示“标识列”的占位符。我希望/需要导入后的每个记录都有一个唯一的键,因此这可以通过简单地创建带有Identity Column的表来实现。我遇到的问题是,要导入的csv/tsv文件仍然需要在文件中包含标识列。如果不在“格式文件”中提供此列的知识,我就无法导入它,因此也无法导入文件。
    3. 我需要解决的最后一项问题是执行一些导入前的数据操作。SQL Server日期有一个限制,它们支持的最早日期是1753年。我的档案中有几个日期是1753年之前的年份,这导致整个记录都失败了。这篇文章和它的答案就是这个最后问题的解决方案。现在,我已经掌握了如何读取和更新这些PowerShell对象中的数据的循环和知识,我可以使用它来更新任何坏数据或执行任何类型的导入前分析。

    PowerShell导入脚本

    #-Import TAB Delimited File (SQL Express and Azure Examples)
    
    #-Declare File Paths
    $SourceFile = "TAB_Delimited.tsv"
    $ExportFile = "TAB_Updated.tsv"
    $FormatFile = "TAB_Delimited.fmt"
    $ErrorFile = "TAB_Delimited_Errors.log"
    
    #---------- 1 Add Column to the beginning of the CSV/TSV file for the Identity Column.  The Export-Csv Commandlet by default also Replaces NewLine_LF (\n) with Cariage Return Line Feed CRLF (\r\n)
    
    #-The main purpose of the below is to add a Column at the beginning of the file as a placeholder for the Identity Column in the Staging Table.
    #-The below will read the Tab Delimited file having EOL Characters as New Lines/Line Feeds \n and turn them into CRLF (Cariage Return, Line Feeds) \r\n.
    #-It will also remove almost all of the double quotes it finds in the file.  The -UseQuotes option is not perfect and so we still have to clean
    #- up the data Post Import and remove any Leading or Trailing Double Quotes using a SQL Update.
    
    Import-Csv $SourceFile -Delimiter "`t" | 
    Select-Object @{Name='_record_number';Expression={'999'}},* | #-Example Adding new column to End Select-Object *,@{Name='column3';Expression={'setvalue'}} 
    ForEach-Object {
        if ( (![string]::IsNullOrEmpty($_.client_dob)) -and ([datetime]$_.client_dob -lt (Get-Date 1900-01-01) ) ) {
            $_.client_dob = (Get-Date $_.client_dob -Year 1900).ToString('yyyy-MM-dd')
            #-Write-Host $_.pcc_id $_.client_dob
        }
        $_
    } |
    Export-Csv $ExportFile -Delimiter "`t" -UseQuotes Never -NoTypeInformation
    
    
    #---------- 2 Import TAB Delimited File Using Format File ---------------
    
    $global:pass = "password"
    
    #-Use an Import File to Bulk Import Data
    
    bcp Database.Schema.Table IN $ExportFile `
    -f $FormatFile `
    -e $ErrorFile `
    -S LOCALSERVERPC\SQLEXPRESS `
    -U sa -P $pass `
    -F 2 `
    #-L 1000
    
    ----------- Or using Azure with Trusted Auth follow the below example ----------------------
    
    #-Use an Import File to Bulk Import Data into Azure
    
    bcp Database.Schema.Table IN $ExportFile `
    -f $FormatFile `
    -e $ErrorFile `
    -S Server_Name_Here `
    -T `
    -F 2 `
    #-L 2000
    
    2 回复  |  直到 1 年前
        1
  •  6
  •   Santiago Squarzon    1 年前

    如何只更新Powershell中现有日期变量的年份?

    你不需要,你只需要创建一个对象的新实例,并将其重新分配给一个变量:

    Get-Date -Year 1900
    

    考虑到你的约会 string 并想将其解析为 datetime 实例,虽然只更改其年份,但您仍然可以使用 Get-Date 将其作为参数传递,并使用 -Year 参数为 mklement0 在评论中指出:

    Get-Date '2023-01-01' -Year 1900
    

    同样的方法不仅适用于 一串 但另一个 日期时间 实例:

    $oldDate = Get-Date -Year 123
    # Saturday, July 17, 0123 5:20:36 PM
    $newDate = Get-Date $oldDate -Year 1900
    # Tuesday, July 17, 1900 5:20:36 PM
    
        2
  •  1
  •   JosefZ    1 年前

    对于(几乎)任何 $DateUpdateYear :

    $DateUpdateYear = $DateUpdateYear.AddYears(1900-$DateUpdateYear.Year)
    

    看见 DateTime.AddYears(Int32) Method :

    参数

    value `Int32`
    

    好几年了。值参数可以是负数或正数。