例如。我有一些混合的日期和时间格式字符串。
"date1": "dd/MM/yyyy",
"date2": "yyyy MM yyyy",
"date3": "h:mmtt",
"date4": "h:mmtt"
我需要检查每种格式都是时间格式还是日期格式。我知道我可以对字符串进行一些向导检查,如果它包含'yyyy'等,但是这感觉很错误并且容易出错。有什么方法可以检查给定的DateTime格式是否仅导致显示时间或仅导致日期?
请明确说明,我不愿意根据格式验证给定日期,也不是给定日期实际上是日期,我只想确定字符串DateTime格式是否仅导致时间部分显示或仅显示日期部分(如果已将其应用于任何DateTime值)。
非常感谢
Stewart
答案 0 :(得分:4)
我会遵循以下原则:
[Flags]
public enum DateFormatStringKind
{
HasNone = 0,
HasDate = 1 << 0,
HasTime = 1 << 1,
HasBoth = HasDate | HasTime
}
public static DateFormatStringKind DescribeFormatString(string s, IFormatProvider provider)
{
DateTime d = new DateTime(2, 2, 2, 1, 1, 1, 1); // DateTime will all non-default values
DateTime d2 = DateTime.ParseExact(d.ToString(s, provider), s, provider, System.Globalization.DateTimeStyles.NoCurrentDateDefault);
DateFormatStringKind result = DateFormatStringKind.HasNone;
if (d2.Date.Ticks != 0)
result |= DateFormatStringKind.HasDate;
if (d2.TimeOfDay != TimeSpan.Zero)
result |= DateFormatStringKind.HasTime;
return result;
}
var culture = System.Globalization.CultureInfo.InvariantCulture;
Console.WriteLine(DescribeFormatString("dd/MM/yyyy", culture));
Console.WriteLine(DescribeFormatString("yyyy MM yyyy", culture));
Console.WriteLine(DescribeFormatString("h:mmtt", culture));
Console.WriteLine(DescribeFormatString("dd h:mmtt", culture));
Console.WriteLine(DescribeFormatString("'literal'", culture));
HasDate
HasDate
HasTime
HasBoth
HasNone
它将具有所有非默认字段的日期转换为使用格式字符串的字符串,然后使用相同的格式字符串返回,然后检查哪些字段在转换后仍然存在。
如果该模式中没有日期组成部分,则“日期”部分将为0001-01-01
,即零日期(从点0开始的零滴答声)。 NoCurrentDateDefault
标志可确保不使用当前日期。
如果模式中没有时间成分,则时间将重置为午夜(从午夜TimeSpan.Zero
开始)。
如果日期模式中至少有一个组成部分(年,月或日),则相应的字段将变为2
,大于日期字段的默认1
,因此无论它是什么组件,都将被检测到。
如果时间模式中至少有一个组成部分(小时,分钟,秒,毫秒),它将变为1
,大于时间字段的默认0
,因此无论它是什么组件,都将再次检测到它。
答案 1 :(得分:0)
我对此没有了解。
您可以使用两种方法,您已经提到了这两种方法。
第一个方法是针对任意测试日期时间进行解析。 GSerg的答案已经涵盖了这一点,但简单来说,您实际上是创建一个虚拟日期,然后将其解析为字符串,然后使用格式字符串将其返回。显然,您的考试时间应该不是00:00的时间,否则您仍然无法分辨;
,并且该日期还应为“今天”或“ 0001年1月1日”以外的日期(请参见Documentation)。第二个选项是检查完整的日期时间格式字符串变量集(请参阅Documentation)-因此,类似这样(尽管在.NET Framework的将来实现中可能会发生变化):
与日期相关的项目如下:
“ d”“ dd”“ ddd”“ dddd”“ g”“ gg”“ M”“ MM”“ MMM”“ MMMM”“ y”“ yy”“ yyy” “ yyyy”“ yyyyy”“ /”
与时间有关的项目如下:
“ f”“ ff”“ fff”“ ffff”“ fffff”“ ffffff”“ fffffff”“ F”“ FF”“ FFF”“ FFFF” “ FFFFF”“ FFFFFF”“ FFFFFFF”“ h”“ hh”“ H”“ HH”“ s”“ ss”“ t”“ tt”“ m” “ mm”“:”
以下内容含糊不清,可能是其中之一-因此我们将忽略这些内容:
“ K”“ z”“ zz”“ zzz”
这为我们提供了以下伪代码:
If date1 contains any of (d,g,M,y,/) then date = true
If date1 contains any of (f,F,h,H,s,t,m,:) then time = true
If date && time then date-time
请注意,这没有考虑转义(\
)字符或包含上述字符之一的字符串文字('...'
)的可能性。要解决此问题,您可以先从格式字符串中删除反斜杠之后或单引号之间的所有字符-但此时最好使用regex。
答案 2 :(得分:0)
有864,000,000,000 ticks in a day
。您可以检查DateTime.Ticks
属性以查看是否可以被该数字整除。如果Ticks
%ticks in a day
为0,则没有时间部分。同样,如果Ticks
/ ticks in a day
为0,则没有日部分。使用Math.DivRem
一次执行除法和模运算。
这是一个帮助班。
public class DateInfo
{
private const long ticksPerDay = 864000000000;
public bool HasDate { get; private set; }
public bool HasTime { get; private set; }
public DateInfo(DateTime date)
{
long timeTicks = 0;
var dayticks = Math.DivRem(date.Ticks, ticksPerDay, out timeTicks);
HasDate = dayticks > 0;
HasTime = timeTicks > 0;
}
public override string ToString()
{
return $"{{{nameof(HasDate)}:{HasDate}, {nameof(HasTime)}:{HasTime}}}";
}
private static readonly DateTime testDate = DateTime.Parse("2/2/2 1:11");
public static DateInfo GetDateInfo(string format)
{
var formatted = testDate.ToString(format);
var dt = DateTime.ParseExact(formatted, format, CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault);
return new DateInfo(dt);
}
}
测试:
var MinDate = DateTime.MinValue;
var OneHour = MinDate.AddHours(1);
var OneDay = MinDate.AddDays(1);
var tests = new Dictionary<string, DateTime>
{
{ nameof(MinDate), DateTime.MinValue },
{ nameof(OneDay), OneDay },
{ nameof(OneHour), OneHour },
{ nameof(DateTime.Now), DateTime.Now },
{ nameof(DateTime.Today), DateTime.Today },
};
var infos = tests.Select(x =>
{
var dateInfo = new DateInfo(x.Value);
return new { x.Key, dateInfo.HasDate, dateInfo.HasTime };
});
tests.ToList().ForEach(test =>
{
var dateInfo = new DateInfo(test.Value);
System.Diagnostics.Debug.WriteLine($"{test.Key}: {dateInfo}");
});
var formatTests = new Dictionary<string, string>
{
{ "date1", "dd/MM/yyyy" },
{ "date2", "yyyy MM dd" },
{ "date3", "h:mmtt" },
{ "date4", "hh:mmtt" }
};
formatTests.ToList().ForEach(test =>
{
var dateInfo = DateInfo.GetDateInfo(test.Value);
System.Diagnostics.Debug.WriteLine($"{test.Key}: {dateInfo}");
});
结果:
MinDate: {HasDate:False, HasTime:False}
OneDay: {HasDate:True, HasTime:False}
OneHour: {HasDate:False, HasTime:True}
Now: {HasDate:True, HasTime:True}
Today: {HasDate:True, HasTime:False}
date1: {HasDate:True, HasTime:False}
date2: {HasDate:True, HasTime:False}
date3: {HasDate:False, HasTime:True}
date4: {HasDate:False, HasTime:True}