我正在尝试使用TDateTime
函数将mmm / yy格式的字符串转换为TryStrToDate
。然而它似乎总是失败。
我创建了一个格式设置记录并设置了日期分隔符和短日期格式。我设置了长日期格式,以表明无论是设置短日期还是长日期格式都会出现问题。
如果我将示例更改为使用dd / mm / yyyy并在2017年1月1日通过,那么它会成功,所以我相信问题可能是格式。我使用以下链接作为参考来创建格式字符串
http://www.delphibasics.co.uk/RTL.asp?Name=formatdatetime
我已经制作了一个演示控制台应用程序,以显示我正在尝试做什么的示例
uses
System.SysUtils;
function ValidateDate(ADate: string): boolean;
var
fs: TFormatSettings;
DateTime: TDateTime;
begin
fs := TFormatSettings.Create();
fs.DateSeparator := '/';
fs.ShortDateFormat := 'mmm/yy';
fs.LongDateFormat := 'mmm/yy';
result := true;
if not TryStrToDate(ADate, DateTime, fs) then
result := false;
end;
begin
try
if not ValidateDate('Oct/16') then
WriteLn('Failed to convert')
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
我会很感激为什么会失败
答案 0 :(得分:7)
您的格式字符串无效。这些格式字符串必须编码日,月和年。你省略了不允许的日子。
您为转换提供的字符串可以省略年份。在这种情况下,假设当前年份。
如果您希望将这些字符串转换为仅几个月和一年,那么请包括假日,例如1,在传递给TryStrToDate
的字符串中。然后使用DecodeDate
获取月份和年份的数值,忽略该日期。
因此,使用'd/mmm/yy'
作为格式,并将'1/' + ADate
作为要转换的字符串传递。
另请注意,它是用于从字符串转换为日期的短日期字符串格式,因此这是您需要设置的唯一格式。
最后,这是一种简单的格式,你可以很容易地直接解析它。
<强>更新强>
正如您所观察到的,并在评论中说明,RTL功能是通过调用ScanDate
来实现的,git filter-branch
仅支持数字月份格式。所以,你所尝试的整个方法,遗憾的是注定要失败。即使你解决了我发现的问题。
我的建议是简单地自己解析字符串,因为它的格式非常简单。
答案 1 :(得分:-1)
根据David的建议,l创建了一个函数,它将月份从字符串转换为Jan,然后调用TryStrToDate获取转换日期。如果格式字符串不包含一天,则默认为01
function ParseDate(ADate: string; AFormatSettings: TFormatSettings): TDateTime;
var
DateData, FormatData: TStringList;
Month, Day, Year: string;
ConvertedDate: Double;
i: integer;
function ConvertMonth(AMonth: string; ALongMonth: boolean = false): string;
var
i: integer;
begin
Result := '-1'; // default to invalid month
if ALongMonth then
begin
for i := 1 to high(AFormatSettings.LongMonthNames) do
begin
if AFormatSettings.LongMonthNames[i] = AMonth then
begin
Result := inttostr(i); // MonthArray starts at index 1 which matches the month
break;
end;
end;
end
else
begin
for i := 1 to high(AFormatSettings.ShortMonthNames) do
begin
if AFormatSettings.ShortMonthNames[i] = AMonth then
begin
Result := inttostr(i); // MonthArray starts at index 1 which matches the month
break;
end;
end;
end;
end;
begin
DateData := TStringList.Create();
FormatData := TStringList.Create();
try
DateData.Delimiter := AFormatSettings.DateSeparator;
DateData.StrictDelimiter := true;
DateData.DelimitedText := ADate;
FormatData.Delimiter := AFormatSettings.DateSeparator;
FormatData.StrictDelimiter := true;
FormatData.DelimitedText := AFormatSettings.ShortDateFormat;
Day := '01';
Month := '01';
Year := '01';
for i := 0 to FormatData.Count - 1 do
begin
if FormatData[i].IndexOf('d') <> -1 then
Day := DateData[i]
else if FormatData[i].IndexOf('m') <> -1 then
begin
if FormatData[i] = 'mmm' then
Month := ConvertMonth(DateData[i])
else if FormatData[i] = 'mmmm' then
Month := ConvertMonth(DateData[i], true)
else
Month := DateData[i]
end
else if FormatData[i].IndexOf('y') <> -1 then
Year := DateData[i]
end;
ADate := Day + AFormatSettings.DateSeparator + Month + AFormatSettings.DateSeparator + Year;
AFormatSettings.ShortDateFormat := 'dd' + AFormatSettings.DateSeparator + 'mm' + AFormatSettings.DateSeparator + 'yyyy';
TryStrToDate(ADate, Result, AFormatSettings);
finally
DateData.free();
FormatData.free();
end;
end;
如果有人能看到任何改进或优化,请告诉我。