- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
在 Windows 中,我想使用精确的格式字符串将 string
解析为 date
。
例如,给定字符串
"6/12/2010"
和格式:
"M/d/yyyy"
我想将字符串转换为日期,同时确保日期与格式匹配。
我还需要能够指定 Y2K 滑动窗口、枢轴。这意味着如果(正确)输入了两位数的年份,我将指定 future 的年数,我认为该年份是。例如:
Two-digit Year Pivot Four-digit year
============== ===== ===============
30 +0 1929
30 +18 1929
30 +19 1929
30 +20 2029
30 +21 2029
30 +100 2029
.NET 已经提供了一个 DateTime.ParseExact
函数,它几乎完全符合我的需要:
date = DateTime.ParseExact("6/12/2010",
DateTimeFormatInfo.ShortDatePattern,
Thread.CurrentThread.CurrentCulture);
除非我不能告诉它 100 年的枢轴值。
更多例子:
String Format Specifier Date
"6/7/2029" "M/d/yyyy" 6/7/2029
"6/7/29" "M/d/yyyy" (invalid, year too short)
"6/7/29" "M/d/yy" 6/7/1929 (+0 pivot)
"6/7/29" "M/d/yy" 6/7/2029 (+100 pivot
"6/7/29" "M/d/yy" 6/7/2029 (+50 pivot)
"6/7/29" "M/d/yy" 6/7/2029
"6/7/2029" "M.d.yyyy" (invalid, incorrect separators)
"6.7.2029" "M.d.yyyy" 6/7/2029
"6.7.2029" "M-d-yyyy" (invalid, incorrect separators)
"6/7/2029" "M/dd/yyyy" (invalid, days requires leading zero)
"6/07/2029" "M/dd/yyyy" (invalid, days requires leading zero)
"6/07/2029" "MM/dd/yyyy" (invalid, months requires leading zero)
"06/07/2029 "MM/dd/yyyy" 6/7/2029
"06/07/2029" "MM/d/yyyy" (invalid, days should not have leading zero)
"06/7/2029" "MM/d/yyyy" 6/7/2029
我知道 Windows 没有将字符串转换为日期的 native API。
是否有任何既定代码可以使用格式说明符将 string
转换为 date
?计算机已经存在了一段时间。一定有人已经解决了这个问题。
以下是您可能会在 Windows 中看到的一些示例格式说明符的列表:
月/日/yyyy
月/日/年
月/日/年
月/日/年
MM/d/yyyy
月/日/年
MM/dd/yyyy
月/日/年
d/M/yyyy
日/月/年
d/MM/yyyy
日/月/年
日/月/年
日/月/年
日/月/年
日/月/年
yyyy/M/d
年/月/日
yyyy/MM/d
yy/MM/d
yyyy/MM/dd
yy/MM/dd
dd MM yyyy
dd.MM.yyyy
最佳答案
我最终不得不屈服并写了一个。解析日期并不简单
class function TDateTimeUtils.TryStrToDateExact(const S, DateFormat: string; out Value: TDateTime): Boolean;
begin
{
Assume Microsoft's de-facto standard for y2k fixup: 2029
1930-2029
}
Result := TDateTimeUtils.TryStrToDateExact(S, DateFormat, 2029, {out}Value);
end;
class function TDateTimeUtils.TryStrToDateExact(const S, DateFormat: string; PivotYear: Integer;
out Value: TDateTime): Boolean;
var
Month, Day, Year: Integer;
Tokens: TStringDynArray;
CurrentToken: string;
i, n: Integer;
Partial: string;
MaxValue: Integer;
nCurrentYear: Integer;
function GetCurrentYear: Word;
var
y, m, d: Word;
begin
DecodeDate(Now, y, m, d);
Result := y;
end;
begin
Result := False;
{
M/dd/yy
Valid pictures codes are
d Day of the month as digits without leading zeros for single-digit days.
dd Day of the month as digits with leading zeros for single-digit days.
ddd Abbreviated day of the week as specified by a LOCALE_SABBREVDAYNAME* value, for example, "Mon" in English (United States).
Windows Vista and later: If a short version of the day of the week is required, your application should use the LOCALE_SSHORTESTDAYNAME* constants.
dddd Day of the week as specified by a LOCALE_SDAYNAME* value.
M Month as digits without leading zeros for single-digit months.
MM Month as digits with leading zeros for single-digit months.
MMM Abbreviated month as specified by a LOCALE_SABBREVMONTHNAME* value, for example, "Nov" in English (United States).
MMMM Month as specified by a LOCALE_SMONTHNAME* value, for example, "November" for English (United States), and "Noviembre" for Spanish (Spain).
y Year represented only by the last digit.
yy Year represented only by the last two digits. A leading zero is added for single-digit years.
yyyy Year represented by a full four or five digits, depending on the calendar used. Thai Buddhist and Korean calendars have five-digit years. The "yyyy" pattern shows five digits for these two calendars, and four digits for all other supported calendars. Calendars that have single-digit or two-digit years, such as for the Japanese Emperor era, are represented differently. A single-digit year is represented with a leading zero, for example, "03". A two-digit year is represented with two digits, for example, "13". No additional leading zeros are displayed.
yyyyy Behaves identically to "yyyy".
g, gg Period/era string formatted as specified by the CAL_SERASTRING value.
The "g" and "gg" format pictures in a date string are ignored if there is no associated era or period string.
PivotYear
The maximum year that a 1 or 2 digit year is assumed to be.
The Microsoft de-factor standard for y2k is 2029. Any value greater
than 29 is assumed to be 1930 or higher.
e.g. 2029:
1930, ..., 2000, 2001,..., 2029
If the PivotYear is between 0 and 99, then PivotYear is assumed to be
a date range in the future. e.g. (assuming this is currently 2010):
Pivot Range
0 1911..2010 (no future years)
1 1912..2011
...
98 2009..2108
99 2010..2099 (no past years)
0 ==> no years in the future
99 ==> no years in the past
}
if Length(S) = 0 then
Exit;
if Length(DateFormat) = 0 then
Exit;
Month := -1;
Day := -1;
Year := -1;
Tokens := TDateTimeUtils.TokenizeFormat(DateFormat);
n := 1; //input string index
for i := Low(Tokens) to High(Tokens) do
begin
CurrentToken := Tokens[i];
if CurrentToken = 'MMMM' then
begin
//Long month names, we don't support yet (you're free to write it)
Exit;
end
else if CurrentToken = 'MMM' then
begin
//Short month names, we don't support yet (you're free to write it)
Exit;
end
else if CurrentToken = 'MM' then
begin
//Month, with leading zero if needed
if not ReadDigitString(S, n, 2{MinDigits}, 2{MaxDigits}, 1{MinValue}, 12{MaxValue}, {var}Month) then Exit;
end
else if CurrentToken = 'M' then
begin
//months
if not ReadDigitString(S, n, 1{MinDigits}, 2{MaxDigits}, 1{MinValue}, 12{MaxValue}, {var}Month) then Exit;
end
else if CurrentToken = 'dddd' then
begin
Exit; //Long day names, we don't support yet (you're free to write it)
end
else if CurrentToken = 'ddd' then
begin
Exit; //Short day names, we don't support yet (you're free to write it);
end
else if CurrentToken = 'dd' then
begin
//If we know what month it is, and even better if we know what year it is, limit the number of valid days to that
if (Month >= 1) and (Month <= 12) then
begin
if Year > 0 then
MaxValue := MonthDays[IsLeapYear(Year), Month]
else
MaxValue := MonthDays[True, Month]; //we don't know the year, assume it's a leap year to be more generous
end
else
MaxValue := 31; //we don't know the month, so assume it's the largest
if not ReadDigitString(S, n, 2{MinDigits}, 2{MaxDigits}, 1{MinValue}, MaxValue{MaxValue}, {var}Day) then Exit;
end
else if CurrentToken = 'd' then
begin
//days
//If we know what month it is, and even better if we know what year it is, limit the number of valid days to that
if (Month >= 1) and (Month <= 12) then
begin
if Year > 0 then
MaxValue := MonthDays[IsLeapYear(Year), Month]
else
MaxValue := MonthDays[True, Month]; //we don't know the year, assume it's a leap year to be more generous
end
else
MaxValue := 31; //we don't know the month, so assume it's the largest
if not ReadDigitString(S, n, 1{MinDigits}, 2{MaxDigits}, 1{MinValue}, MaxValue{MaxValue}, {var}Day) then Exit;
end
else if (CurrentToken = 'yyyy') or (CurrentToken = 'yyyyy') then
begin
//Year represented by a full four or five digits, depending on the calendar used.
{
Thai Buddhist and Korean calendars have five-digit years.
The "yyyy" pattern shows five digits for these two calendars,
and four digits for all other supported calendars.
Calendars that have single-digit or two-digit years, such as for
the Japanese Emperor era, are represented differently.
A single-digit year is represented with a leading zero, for
example, "03". A two-digit year is represented with two digits,
for example, "13". No additional leading zeros are displayed.
}
if not ReadDigitString(S, n, 4{MinDigits}, 4{MaxDigits}, 0{MinValue}, 9999{MaxValue}, {var}Year) then Exit;
end
else if CurrentToken = 'yyy' then
begin
//i'm not sure what this would look like, so i'll ignore it
Exit;
end
else if CurrentToken = 'yy' then
begin
//Year represented only by the last two digits. A leading zero is added for single-digit years.
if not ReadDigitString(S, n, 2{MinDigits}, 2{MaxDigits}, 0{MinValue}, 99{MaxValue}, {var}Year) then Exit;
nCurrentYear := GetCurrentYear;
Year := (nCurrentYear div 100 * 100)+Year;
if (PivotYear < 100) and (PivotYear >= 0) then
begin
//assume pivotyear is a delta from this year, not an absolute value
PivotYear := nCurrentYear+PivotYear;
end;
//Check the pivot year value
if Year > PivotYear then
Year := Year - 100;
end
else if CurrentToken = 'y' then
begin
//Year represented only by the last digit.
if not ReadDigitString(S, n, 1{MinDigits}, 1{MaxDigits}, 0{MinValue}, 9{MaxValue}, {var}Year) then Exit;
nCurrentYear := GetCurrentYear;
Year := (nCurrentYear div 10 * 10)+Year;
if (PivotYear < 100) and (PivotYear >= 0) then
begin
//assume pivotyear is a delta from this year, not an absolute value
PivotYear := nCurrentYear+PivotYear;
end;
//Check the pivot year value
if Year > PivotYear then
Year := Year - 100;
end
else
begin
//The input string should contains CurrentToken starting at n
Partial := Copy(S, n, Length(CurrentToken));
Inc(n, Length(CurrentToken));
if Partial <> CurrentToken then
Exit;
end;
end;
//If there's still stuff left over in the string, then it's not valid
if n <> Length(s)+1 then
begin
Result := False;
Exit;
end;
if Day > MonthDays[IsLeapYear(Year), Month] then
begin
Result := False;
Exit;
end;
try
Value := EncodeDate(Year, Month, Day);
except
Result := False;
Exit;
end;
Result := True;
end;
class function TDateTimeUtils.TokenizeFormat(fmt: string): TStringDynArray;
var
i: Integer;
partial: string;
function IsDateFormatPicture(ch: AnsiChar): Boolean;
begin
case ch of
'M','d','y': Result := True;
else Result := False;
end;
end;
begin
SetLength(Result, 0);
if Length(fmt) = 0 then
Exit;
//format is only one character long? If so then that's the tokenized entry
if Length(fmt)=1 then
begin
SetLength(Result, 1);
Result[0] := fmt;
end;
partial := fmt[1];
i := 2;
while i <= Length(fmt) do
begin
//If the characters in partial are a format picture, and the character in fmt is not the same picture code then write partial to result, and reset partial
if IsDateFormatPicture(partial[1]) then
begin
//if the current fmt character is different than the running partial picture
if (partial[1] <> fmt[i]) then
begin
//Move the current partial to the output
//and start a new partial
SetLength(Result, Length(Result)+1);
Result[High(Result)] := partial;
Partial := fmt[i];
end
else
begin
//the current fmt character is more of the same format picture in partial
//Add it to the partial
Partial := Partial + fmt[i];
end;
end
else
begin
//The running partial is not a format picture.
//If the current fmt character is a picture code, then write out the partial and start a new partial
if IsDateFormatPicture(fmt[i]) then
begin
//Move the current partial to the output
//and start a new partial
SetLength(Result, Length(Result)+1);
Result[High(Result)] := partial;
Partial := fmt[i];
end
else
begin
//The current fmt character is another non-picture code. Add it to the running partial
Partial := Partial + fmt[i];
end;
end;
Inc(i);
Continue;
end;
//If we have a running partial, then add it to the output
if partial <> '' then
begin
SetLength(Result, Length(Result)+1);
Result[High(Result)] := partial;
end;
end;
class function TDateTimeUtils.ReadDigitString(const S: string; var Pos: Integer;
MinDigits, MaxDigits: Integer; MinValue, MaxValue: Integer;
var Number: Integer): Boolean;
var
Digits: Integer;
Value: Integer;
Partial: string;
CandidateNumber: Integer;
CandidateDigits: Integer;
begin
Result := False;
CandidateNumber := -1;
CandidateDigits := 0;
Digits := MinDigits;
while Digits <= MaxDigits do
begin
Partial := Copy(S, Pos, Digits);
if Length(Partial) < Digits then
begin
//we couldn't get all we wanted. We're done; use whatever we've gotten already
Break;
end;
//Check that it's still a number
if not TryStrToInt(Partial, Value) then
Break;
//Check that it's not too big - meaning that getting anymore wouldn't work
if (Value > MaxValue) then
Break;
if (Value >= MinValue) then
begin
//Hmm, looks good. Keep it as our best possibility
CandidateNumber := Value;
CandidateDigits := Digits;
end;
Inc(Digits); //try to be greedy, grabbing even *MORE* digits
end;
if (CandidateNumber >= 0) or (CandidateDigits > 0) then
begin
Inc(Pos, CandidateDigits);
Number := CandidateNumber;
Result := True;
end;
end;
关于windows - Win32 : How to convert string to a date?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3062789/
数据框有一个字符串类型的日期列 '2017-01-01' 它被转换为 DateType() df = df.withColumn('date', col('date_string').cast(Dat
这个问题在这里已经有了答案: What is "x && foo()"? (5 个答案) 关闭 8 年前。 我在 bootstrap-datepicker.js 文件中遇到过这个。 作者在_setD
我有一个数据库 utc 字符串,我正在传递到 Date(attrs.endDate),然后通过 new Date() 减去当前的 utc 日期,但我无法得到它来为我提供 2 个 utc 日期的正确差异
这个问题在这里已经有了答案: how to determine if 2 dates object equals each other? [duplicate] (3 个答案) 关闭 6 年前。 我
这个问题已经有答案了: How can I convert "/Date(1399739515000)/" into date format in JavaScript? (3 个回答) 已关闭 8
根据MDN ,我们只能将以下类型的参数传递给 Date 构造函数: new Date(); new Date(value); // Unix timestamp new Date(dateString
我从表中获取所有项目: endDate >= 现在 endDate 为 NULL published 等于 1。 这是我所拥有的,但它给了我 0 个项目: $items = Items::orderB
此查询需要很长时间才能完成。当我将 WHERE 子句设置为 new_dl >= '2014-01-01' 时,查询大约需要 6 分钟才能浏览大约 3 个月的数据。现在不知道为什么这个应该从 12 个月
我有一个正在为项目开发的小型 Java 程序,它使用 JavaMail 从指定的 URI 中提取用户的收件箱,然后开始处理消息。 在 Outlook 中,属性菜单中有一个功能可以设置邮件的到期日期,它
我想在获取 Date.getHours()、Date.getMinutes() 和 Date.getSeconds() 的值后格式化输出>. 这是一条漫长的路: var dt = new Date()
我发现java.text.DateFormat有两种格式化日期的方法。一种是采用 Date 参数,另一种是采用 Object 参数。我检查了DateFormat源代码,似乎他们调用了不同的内部方法。
我有两个对象,p4 和 p5,它们都具有 Date 属性。在某些时候,构造函数工作正常: p4.setClickDate(new Date(System.currentTimeMillis() - 8
我是使用 Sequelize 和 Node.js 的新手,但我的代码中存在日期比较问题。 User.findOne({ where: { resetToken: passwordToken,
我正在使用一个名为 fullcalendar 的 jquery 日历。当用户单击某一天时,他们将被发送到另一个页面以创建该天的事件。单击的日期作为 date 提供。然后通过下面的函数运行将其转换为 U
我有一个列表列表,每个列表中都有整数值,代表 8 年期间的日期。 dates = [[2014, 11, 14], [2014, 11, 13], ....., [2013, 12, 01]
我有两个表: 首先是TimeValues(示例) time | value 12/28/18 | 5.6 01/03/19 | 5.6 01/04/19 | 5.6 01/09/19 | 5.
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
像这样实例化的日期对象: new Date("2011-12-13") 返回一个认为自己是星期一的日期对象: Date {Mon Dec 12 2011 16:00:00 GMT-0800 (PST)
我需要选择入住日期和退房日期在指定日期范围之间的房价。这些费率根据其条件单独命名。房费取决于所选日期。这是我的代码: rate_eb rate_name rate_starts rat
我有 [Int64:[String:String]] 其中 Int64 是时间戳。如何检测和删除 [String:String] 中的参数之一是 ["name"] = "test" 并重复多次的同一天
我是一名优秀的程序员,十分优秀!