我正在C#中为一个
winforms应用程序实现一个模糊日期控件.模糊日期应该能够采用模糊值
>去年六月
> 2小时前
> 2个月前
>上周
>昨天
>去年
等等
有没有“模糊”日期时间选择器的示例实现?
任何实现这种控制的想法都将不胜感激
解决方法
解析很简单.它可以被实现为一堆正则表达式和一些日期计算.
以下样品可以轻松扩展,以满足您的需要.
我已经大致测试了它,它至少可以用于以下字符串:
>下个月,明年,
>接下来的4个月,接下来3天
> 3天前,5小时前
>明天,昨天
>去年,上个月,
>最后一个星期,下个星期五
>上个六月,接下来可能,
> 2008年1月1日,
> 2019年6月,2009/01/01
助手类:
class FuzzyDateTime { static List<string> dayList = new List<string>() { "sun","mon","tue","wed","thu","fri","sat" }; static List<IDateTimePattern> parsers = new List<IDateTimePattern>() { new RegexDateTimePattern ( @"next +([2-9]\d*) +months",delegate (Match m) { var val = int.Parse(m.Groups[1].Value); return DateTime.Now.AddMonths(val); } ),new RegexDateTimePattern ( @"next +month",delegate (Match m) { return DateTime.Now.AddMonths(1); } ),new RegexDateTimePattern ( @"next +([2-9]\d*) +days",delegate (Match m) { var val = int.Parse(m.Groups[1].Value); return DateTime.Now.AddDays(val); } ),new RegexDateTimePattern ( @"([2-9]\d*) +months +ago",delegate (Match m) { var val = int.Parse(m.Groups[1].Value); return DateTime.Now.AddMonths(-val); } ),new RegexDateTimePattern ( @"([2-9]\d*) days +ago",delegate (Match m) { var val = int.Parse(m.Groups[1].Value); return DateTime.Now.AddDays(-val); } ),new RegexDateTimePattern ( @"([2-9]\d*) *h(ours)? +ago",new RegexDateTimePattern ( @"tomorrow",delegate (Match m) { return DateTime.Now.AddDays(1); } ),new RegexDateTimePattern ( @"today",delegate (Match m) { return DateTime.Now; } ),new RegexDateTimePattern ( @"yesterday",delegate (Match m) { return DateTime.Now.AddDays(-1); } ),new RegexDateTimePattern ( @"(last|next) *(year|month)",delegate (Match m) { int direction = (m.Groups[1].Value == "last")? -1 :1; switch(m.Groups[2].Value) { case "year": return new DateTime(DateTime.Now.Year+direction,1,1); case "month": return new DateTime(DateTime.Now.Year,DateTime.Now.Month+direction,1); } return DateTime.MinValue; } ),new RegexDateTimePattern ( String.Format(@"(last|next) *({0}).*",String.Join("|",dayList.ToArray())),//handle weekdays delegate (Match m) { var val = m.Groups[2].Value; var direction = (m.Groups[1].Value == "last")? -1 :1; var dayOfWeek = dayList.IndexOf(val.Substring(0,3)); if (dayOfWeek >= 0) { var diff = direction*(dayOfWeek - (int)DateTime.Today.DayOfWeek); if (diff <= 0 ) { diff = 7 + diff; } return DateTime.Today.AddDays(direction * diff); } return DateTime.MinValue; } ),new RegexDateTimePattern ( @"(last|next) *(.+)",// to parse months using DateTime.TryParse delegate (Match m) { DateTime dt; int direction = (m.Groups[1].Value == "last")? -1 :1; var s = String.Format("{0} {1}",m.Groups[2].Value,DateTime.Now.Year + direction); if (DateTime.TryParse(s,out dt)) { return dt; } else { return DateTime.MinValue; } } ),new RegexDateTimePattern ( @".*",//as final resort parse using DateTime.TryParse delegate (Match m) { DateTime dt; var s = m.Groups[0].Value; if (DateTime.TryParse(s,}; public static DateTime Parse(string text) { text = text.Trim().ToLower(); var dt = DateTime.Now; foreach (var parser in parsers) { dt = parser.Parse(text); if (dt != DateTime.MinValue) break; } return dt; } } interface IDateTimePattern { DateTime Parse(string text); } class RegexDateTimePattern : IDateTimePattern { public delegate DateTime Interpreter(Match m); protected Regex regEx; protected Interpreter inter; public RegexDateTimePattern(string re,Interpreter inter) { this.regEx = new Regex(re); this.inter = inter; } public DateTime Parse(string text) { var m = regEx.Match(text); if (m.Success) { return inter(m); } return DateTime.MinValue; } }
用法示例:
var val = FuzzyDateTime.Parse(textBox1.Text); if (val != DateTime.MinValue) label1.Text = val.ToString(); else label1.Text = "unknown value";