问题描述
我实现在C#中的WinForms应用程序模糊控制的日期。模糊的日期应该能够采取模糊值如
I am implementing a Fuzzy Date control in C# for a winforms application. The Fuzzy Date should be able to take fuzzy values like
- 去年六月
- 2小时前
- 2个月前
- 上周
- 昨天
- 去年
之类的
是否有模糊的日期时间选择器中的任何样本实现?
Are there any sample implementations of "Fuzzy" Date Time Pickers?
来实现这样的控制将AP preciated任何想法
Any ideas to implement such a control would be appreciated
PS :
我知道谈及 href=\"http://stackoverflow.com/questions/822124/fuzzy-date-algorithm\">和的,我期待为开发这样的控制
PS:I am aware of the fuzzy date algorithm spoken about here and here, I am really looking for any ideas and inspirations for developing such a control
推荐答案
解析是很容易的。它可以实现为正则表达式的一堆有的日期计算。
The parsing is quite easy. It can be implemented as bunch of regexps and some date calculations.
下面的示例可以很容易地扩展,以满足您的需求。
我粗略地测试了它和它的作品至少在以下字符串:
The sample below can be easily extended to suit your needs.I've roughly tested it and it works at least for the following strings:
- 下个月,明年,
- 接下来的4个月,接下来的3天
- 3天前,14小时前
- 明天,昨天
- 去年最后一个月,
- 最后周二,周五旁边
- 去年六月,明年5月,
- 2008年1月,2009年1月1日,
- 2019年6月,2009/01/01
helper类:
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",
delegate (Match m) {
var val = int.Parse(m.Groups[1].Value);
return DateTime.Now.AddMonths(-val);
}
),
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, out dt)) {
return dt;
} else {
return DateTime.MinValue;
}
}
),
};
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";
这篇关于模糊日期时间在C#.NET选取器控件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!