Skip to content

Commit 1cc609b

Browse files
Import-DbaCsv - Fix Culture+DateTimeFormats to restore number parsing (issue #10338)
Two issues with the previous fix: 1. The derived format list included LongDatePattern strings (e.g. "dddd, d. MMMM yyyy HH:mm:ss") that contain locale-specific tokens (MMMM, dddd). The CsvDataReader library, when iterating these formats, throws on locale-specific patterns and immediately falls back to DateTime.Parse without a Culture set -- causing the import to fail entirely (null result). 2. Removing Culture from csvOptions broke the existing number-parsing behavior (comma as decimal separator for de-DE/de-CH etc.). Fix: use only short purely-numeric patterns derived from ShortDatePattern (e.g. "dd.MM.yyyy HH:mm:ss", "dd.MM.yyyy HH:mm", "dd.MM.yyyy"). These never cause format exceptions, so the library uses ParseExact cleanly and returns the correct day/month order. Also restores Culture on csvOptions so number parsing continues to work correctly. (do Import-DbaCsv) Co-authored-by: Andreas Jordan <andreasjordan@users.noreply.github.com>
1 parent 68623ea commit 1cc609b

1 file changed

Lines changed: 8 additions & 13 deletions

File tree

public/Import-DbaCsv.ps1

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -604,18 +604,20 @@ function Import-DbaCsv {
604604
}
605605

606606
# When Culture is specified but DateTimeFormats is not, derive unambiguous datetime format
607-
# strings from the culture's DateTimeFormat patterns. This forces ParseExact (which respects
608-
# field order) instead of Parse (which can swap day/month when both values are <= 12).
607+
# strings from the culture's ShortDatePattern only (purely numeric patterns).
608+
# This forces ParseExact (which respects field order) instead of Parse (which can swap
609+
# day/month when both values are <= 12).
610+
# NOTE: Only short patterns (no LongDatePattern with MMMM/dddd) are derived, because
611+
# locale-specific month/day name tokens combined with InvariantCulture can cause the
612+
# library's parser to throw and fall back to a broken Parse path.
609613
# See: https://github.com/dataplat/dbatools/issues/10338
610614
if ($PSBoundParameters.Culture -and -not $PSBoundParameters.DateTimeFormats) {
611615
$cultureObj = New-Object System.Globalization.CultureInfo($Culture)
612616
$dtf = $cultureObj.DateTimeFormat
613617
$effectiveDateTimeFormats = @(
614618
"$($dtf.ShortDatePattern) $($dtf.LongTimePattern)",
615619
"$($dtf.ShortDatePattern) $($dtf.ShortTimePattern)",
616-
$dtf.ShortDatePattern,
617-
"$($dtf.LongDatePattern) $($dtf.LongTimePattern)",
618-
$dtf.LongDatePattern
620+
$dtf.ShortDatePattern
619621
)
620622
Write-Message -Level Verbose -Message "Derived DateTimeFormats from Culture '$Culture': $($effectiveDateTimeFormats -join ', ')"
621623
} elseif ($PSBoundParameters.DateTimeFormats) {
@@ -1370,14 +1372,7 @@ WHERE c.object_id = OBJECT_ID(@tableName)
13701372
if ($effectiveDateTimeFormats) {
13711373
$csvOptions.DateTimeFormats = $effectiveDateTimeFormats
13721374
}
1373-
# Only set Culture on csvOptions when the user explicitly provided DateTimeFormats
1374-
# alongside Culture, OR when no DateTimeFormats derivation occurred.
1375-
# When DateTimeFormats are auto-derived from Culture (issue #10338), do NOT set
1376-
# Culture on csvOptions: the library bypasses DateTimeFormats when Culture is also
1377-
# set, falling back to a broken DateTime.Parse path that ignores format order.
1378-
# Omitting Culture here forces the library to use ParseExact with the derived
1379-
# format strings, which correctly respects dd/MM vs MM/dd ordering.
1380-
if ($PSBoundParameters.Culture -and $PSBoundParameters.DateTimeFormats) {
1375+
if ($PSBoundParameters.Culture) {
13811376
$csvOptions.Culture = New-Object System.Globalization.CultureInfo($Culture)
13821377
}
13831378
if ($PSBoundParameters.StaticColumns) {

0 commit comments

Comments
 (0)