我试图使用TDateTime
函数将mmm/yy格式的字符串转换为TryStrToDate
。然而,它似乎总是失败。
我创建格式设置记录,并设置日期分隔符和短日期格式。我设置了长日期格式,以显示问题发生,无论我设置短日期格式还是长日期格式。
如果我将示例更改为使用dd/mm/yyyy,并在2017年02月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.
我想知道为什么这样做失败了
发布于 2017-02-03 02:12:56
根据David的建议,我创建了一个函数,该函数将把字符串ie Jan转换为01,然后调用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;
如果有人能看到任何改进或优化,请告诉我。
发布于 2017-02-01 07:27:50
格式字符串无效。这些格式字符串必须编码日、月和年。你省略了不允许的一天。
您为转换提供的字符串允许省略年份。在这种情况下,假定是本年度。
如果希望将这些字符串转换为仅几个月和一年,那么在传递给TryStrToDate
的字符串中包含一个假的日期,例如1。然后使用DecodeDate
获取月份和年份的数值,忽略日期。
因此,使用'd/mmm/yy'
作为格式,传递'1/' + ADate
作为要转换的字符串。
还请注意,用于将字符串转换为date的是短日期字符串格式,因此这是您需要设置的唯一格式。
最后,这是一种非常简单的格式,您可以很容易地直接解析它。
更新
正如您在注释中所看到的,RTL功能是通过调用ScanDate
实现的,它只支持数字月份格式。因此,不幸的是,你所尝试的整个方法注定要失败。即使你解决了我发现的问题。
我的建议是自己简单地解析字符串,因为它的格式非常简单。
https://stackoverflow.com/questions/41974096
复制相似问题