Skip to content

Commit 00ce7d9

Browse files
2881028810
authored andcommitted
- 增加 Sqlite 表达式解析 yyyyMMdd 常用 c# 日期格式化;
1 parent 795ba9c commit 00ce7d9

File tree

2 files changed

+97
-21
lines changed

2 files changed

+97
-21
lines changed

FreeSql.Tests/FreeSql.Tests/Sqlite/SqliteExpression/DateTimeTest.cs

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,52 @@ class TestTypeParentInfo
4141
public List<TestTypeInfo> Types { get; set; }
4242
public DateTime Time2 { get; set; }
4343
}
44+
45+
[Fact]
46+
public void this_ToString()
47+
{
48+
var data = new List<object>();
49+
data.Add(select.Where(a => a.CreateTime.ToString().Equals(DateTime.Now)).ToList());
50+
data.Add(select.Where(a => a.Type.Time.AddYears(1).ToString().Equals(DateTime.Now)).ToList());
51+
data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1).ToString().Equals(DateTime.Now)).ToList());
52+
//SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5
53+
//FROM `tb_topic111333` a
54+
//WHERE ((date_format(a.`CreateTime`, '%Y-%m-%d %H:%i:%s.%f') = now()));
55+
56+
//SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9
57+
//FROM `tb_topic111333` a, `TestTypeInfo333` a__Type
58+
//WHERE ((date_format(date_add(a__Type.`Time`, interval (1) year), '%Y-%m-%d %H:%i:%s.%f') = now()));
59+
60+
//SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9
61+
//FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent
62+
//WHERE ((date_format(date_add(a__Type__Parent.`Time2`, interval (1) year), '%Y-%m-%d %H:%i:%s.%f') = now()))
63+
64+
g.sqlite.Insert(new Topic()).ExecuteAffrows();
65+
var dtn = DateTime.Parse("2020-1-1 0:0:0");
66+
var dts = Enumerable.Range(1, 12).Select(a => dtn.AddMonths(a))
67+
.Concat(Enumerable.Range(1, 31).Select(a => dtn.AddDays(a)))
68+
.Concat(Enumerable.Range(1, 24).Select(a => dtn.AddHours(a)))
69+
.Concat(Enumerable.Range(1, 60).Select(a => dtn.AddMinutes(a)))
70+
.Concat(Enumerable.Range(1, 60).Select(a => dtn.AddSeconds(a)));
71+
foreach (var dt in dts)
72+
{
73+
Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm:ss.fff"), select.First(a => dt.ToString()));
74+
Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm:ss"), select.First(a => dt.ToString("yyyy-MM-dd HH:mm:ss")));
75+
Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm"), select.First(a => dt.ToString("yyyy-MM-dd HH:mm")));
76+
Assert.Equal(dt.ToString("yyyy-MM-dd HH"), select.First(a => dt.ToString("yyyy-MM-dd HH")));
77+
Assert.Equal(dt.ToString("yyyy-MM-dd"), select.First(a => dt.ToString("yyyy-MM-dd")));
78+
Assert.Equal(dt.ToString("yyyy-MM"), select.First(a => dt.ToString("yyyy-MM")));
79+
Assert.Equal(dt.ToString("yyyyMMddHHmmss"), select.First(a => dt.ToString("yyyyMMddHHmmss")));
80+
Assert.Equal(dt.ToString("yyyyMMddHHmm"), select.First(a => dt.ToString("yyyyMMddHHmm")));
81+
Assert.Equal(dt.ToString("yyyyMMddHH"), select.First(a => dt.ToString("yyyyMMddHH")));
82+
Assert.Equal(dt.ToString("yyyyMMdd"), select.First(a => dt.ToString("yyyyMMdd")));
83+
Assert.Equal(dt.ToString("yyyyMM"), select.First(a => dt.ToString("yyyyMM")));
84+
Assert.Equal(dt.ToString("yyyy"), select.First(a => dt.ToString("yyyy")));
85+
Assert.Equal(dt.ToString("HH:mm:ss"), select.First(a => dt.ToString("HH:mm:ss")));
86+
Assert.Equal(dt.ToString("yyyy MM dd HH mm ss yy M d H hh h"), select.First(a => dt.ToString("yyyy MM dd HH mm ss yy M d H hh h")));
87+
Assert.Equal(dt.ToString("yyyy MM dd HH mm ss yy M d H hh h m s tt t").Replace("上午", "AM").Replace("下午", "PM").Replace("上", "A").Replace("下", "P"), select.First(a => dt.ToString("yyyy MM dd HH mm ss yy M d H hh h m s tt t")));
88+
}
89+
}
4490
[Fact]
4591
public void Now()
4692
{
@@ -587,26 +633,6 @@ public void this_Equals()
587633
//FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent
588634
//WHERE ((date_add(a__Type__Parent.`Time2`, interval (1) year) = now()))
589635
}
590-
[Fact]
591-
public void this_ToString()
592-
{
593-
var data = new List<object>();
594-
data.Add(select.Where(a => a.CreateTime.ToString().Equals(DateTime.Now)).ToList());
595-
data.Add(select.Where(a => a.Type.Time.AddYears(1).ToString().Equals(DateTime.Now)).ToList());
596-
data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1).ToString().Equals(DateTime.Now)).ToList());
597-
//SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5
598-
//FROM `tb_topic111333` a
599-
//WHERE ((date_format(a.`CreateTime`, '%Y-%m-%d %H:%i:%s.%f') = now()));
600-
601-
//SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9
602-
//FROM `tb_topic111333` a, `TestTypeInfo333` a__Type
603-
//WHERE ((date_format(date_add(a__Type.`Time`, interval (1) year), '%Y-%m-%d %H:%i:%s.%f') = now()));
604-
605-
//SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9
606-
//FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent
607-
//WHERE ((date_format(date_add(a__Type__Parent.`Time2`, interval (1) year), '%Y-%m-%d %H:%i:%s.%f') = now()))
608-
}
609-
610636
[Fact]
611637
public void DateTime_Compare()
612638
{

Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Linq;
77
using System.Linq.Expressions;
88
using System.Text;
9+
using System.Text.RegularExpressions;
910

1011
namespace FreeSql.Sqlite
1112
{
@@ -396,7 +397,56 @@ public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression ex
396397
break;
397398
case "Equals": return $"({left} = {args1})";
398399
case "CompareTo": return $"(strftime('%s',{left})-strftime('%s',{args1}))";
399-
case "ToString": return exp.Arguments.Count == 0 ? $"strftime('%Y-%m-%d %H:%M.%f',{left})" : null;
400+
case "ToString":
401+
if (exp.Arguments.Count == 0) return $"strftime('%Y-%m-%d %H:%M:%f',{left})";
402+
switch (args1)
403+
{
404+
case "'yyyy-MM-dd HH:mm:ss'": return $"strftime('%Y-%m-%d %H:%M:%S',{left})";
405+
case "'yyyy-MM-dd HH:mm'": return $"strftime('%Y-%m-%d %H:%M',{left})";
406+
case "'yyyy-MM-dd HH'": return $"strftime('%Y-%m-%d %H',{left})";
407+
case "'yyyy-MM-dd'": return $"strftime('%Y-%m-%d',{left})";
408+
case "'yyyy-MM'": return $"strftime('%Y-%m',{left})";
409+
case "'yyyyMMddHHmmss'": return $"strftime('%Y%m%d%H%M%S',{left})";
410+
case "'yyyyMMddHHmm'": return $"strftime('%Y%m%d%H%M',{left})";
411+
case "'yyyyMMddHH'": return $"strftime('%Y%m%d%H',{left})";
412+
case "'yyyyMMdd'": return $"strftime('%Y%m%d',{left})";
413+
case "'yyyyMM'": return $"strftime('%Y%m',{left})";
414+
case "'yyyy'": return $"strftime('%Y',{left})";
415+
case "'HH:mm:ss'": return $"strftime('%H:%M:%S',{left})";
416+
}
417+
args1 = Regex.Replace(args1, "(yyyy|MM|dd|HH|mm|ss)", m =>
418+
{
419+
switch (m.Groups[1].Value)
420+
{
421+
case "yyyy": return $"%Y";
422+
case "MM": return $"%_a1";
423+
case "dd": return $"%_a2";
424+
case "HH": return $"%_a3";
425+
case "mm": return $"%_a4";
426+
case "ss": return $"%S";
427+
}
428+
return m.Groups[0].Value;
429+
});
430+
var isMatched = false;
431+
args1 = Regex.Replace(args1, "(yy|M|d|H|hh|h|m|s|tt|t)", m =>
432+
{
433+
isMatched = true;
434+
switch (m.Groups[1].Value)
435+
{
436+
case "yy": return $"',{left}) || substr(strftime('%Y',{left}),3,2) || strftime('";
437+
case "M": return $"',{left}) || ltrim(strftime('%m',{left}),'0') || strftime('";
438+
case "d": return $"',{left}) || ltrim(strftime('%d',{left}),'0') || strftime('";
439+
case "H": return $"',{left}) || case when substr(strftime('%H',{left}),1,1) = '0' then substr(strftime('%H',{left}),2,1) else strftime('%H',{left}) end || strftime('";
440+
case "hh": return $"',{left}) || case cast(case when substr(strftime('%H',{left}),1,1) = '0' then substr(strftime('%H',{left}),2,1) else strftime('%H',{left}) end as smallint) % 12 when 0 then '12' when 1 then '01' when 2 then '02' when 3 then '03' when 4 then '04' when 5 then '05' when 6 then '06' when 7 then '07' when 8 then '08' when 9 then '09' when 10 then '10' when 11 then '11' end || strftime('";
441+
case "h": return $"',{left}) || case cast(case when substr(strftime('%H',{left}),1,1) = '0' then substr(strftime('%H',{left}),2,1) else strftime('%H',{left}) end as smallint) % 12 when 0 then '12' when 1 then '1' when 2 then '2' when 3 then '3' when 4 then '4' when 5 then '5' when 6 then '6' when 7 then '7' when 8 then '8' when 9 then '9' when 10 then '10' when 11 then '11' end || strftime('";
442+
case "m": return $"',{left}) || case when substr(strftime('%M',{left}),1,1) = '0' then substr(strftime('%M',{left}),2,1) else strftime('%M',{left}) end || strftime('";
443+
case "s": return $"',{left}) || case when substr(strftime('%S',{left}),1,1) = '0' then substr(strftime('%S',{left}),2,1) else strftime('%S',{left}) end || strftime('";
444+
case "tt": return $"',{left}) || case when cast(case when substr(strftime('%H',{left}),1,1) = '0' then substr(strftime('%H',{left}),2,1) else strftime('%H',{left}) end as smallint) >= 12 then 'PM' else 'AM' end || strftime('";
445+
case "t": return $"',{left}) || case when cast(case when substr(strftime('%H',{left}),1,1) = '0' then substr(strftime('%H',{left}),2,1) else strftime('%H',{left}) end as smallint) >= 12 then 'P' else 'A' end || strftime('";
446+
}
447+
return m.Groups[0].Value;
448+
}).Replace("%_a1", "%m").Replace("%_a2", "%d").Replace("%_a3", "%H").Replace("%_a4", "%M");
449+
return isMatched == false ? $"strftime({args1},{left})" : $"(strftime({args1},{left}))".Replace($"strftime('',{left})", "''");
400450
}
401451
}
402452
return null;

0 commit comments

Comments
 (0)