diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/SqlServerExpression/DateTimeTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/SqlServerExpression/DateTimeTest.cs index ab4708bc..bdeeab9e 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/SqlServerExpression/DateTimeTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/SqlServerExpression/DateTimeTest.cs @@ -41,6 +41,31 @@ namespace FreeSql.Tests.Odbc.SqlServerExpression public List Types { get; set; } public DateTime Time2 { get; set; } } + + [Fact] + public void this_ToString() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.ToString().Equals(DateTime.Now)).ToList()); + data.Add(select.Where(a => a.Type.Time.AddYears(1).ToString().Equals(DateTime.Now)).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1).ToString().Equals(DateTime.Now)).ToList()); + + g.sqlserver.Insert(new Topic()).ExecuteAffrows(); + foreach (var dt in new[] { DateTime.Parse("2020-5-6 0:1:2"), DateTime.Parse("2020-11-16 13:21:22"), }) + { + Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm:ss.fff"), select.First(a => dt.ToString())); + Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm:ss"), select.First(a => dt.ToString("yyyy-MM-dd HH:mm:ss"))); + Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm"), select.First(a => dt.ToString("yyyy-MM-dd HH:mm"))); + Assert.Equal(dt.ToString("yyyy-MM-dd HH"), select.First(a => dt.ToString("yyyy-MM-dd HH"))); + Assert.Equal(dt.ToString("yyyy-MM-dd"), select.First(a => dt.ToString("yyyy-MM-dd"))); + Assert.Equal(dt.ToString("yyyy-MM"), select.First(a => dt.ToString("yyyy-MM"))); + Assert.Equal(dt.ToString("yyyyMMdd"), select.First(a => dt.ToString("yyyyMMdd"))); + Assert.Equal(dt.ToString("yyyyMM"), select.First(a => dt.ToString("yyyyMM"))); + Assert.Equal(dt.ToString("yyyy"), select.First(a => dt.ToString("yyyy"))); + Assert.Equal(dt.ToString("HH:mm:ss"), select.First(a => dt.ToString("HH:mm:ss"))); + 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"))); + } + } [Fact] public void Now() { @@ -269,14 +294,6 @@ namespace FreeSql.Tests.Odbc.SqlServerExpression data.Add(select.Where(a => a.Type.Time.AddYears(1).Equals(DateTime.Now)).ToList()); data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1).Equals(DateTime.Now)).ToList()); } - [Fact] - public void this_ToString() - { - var data = new List(); - data.Add(select.Where(a => a.CreateTime.ToString().Equals(DateTime.Now)).ToList()); - data.Add(select.Where(a => a.Type.Time.AddYears(1).ToString().Equals(DateTime.Now)).ToList()); - data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1).ToString().Equals(DateTime.Now)).ToList()); - } [Fact] public void DateTime_Compare() diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/DateTimeTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/DateTimeTest.cs index aafaf6a9..284cdaf3 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/DateTimeTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/DateTimeTest.cs @@ -49,6 +49,31 @@ namespace FreeSql.Tests.SqlServerExpression public List Types { get; set; } public DateTime Time2 { get; set; } } + + [Fact] + public void this_ToString() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.ToString().Equals(DateTime.Now)).ToList()); + data.Add(select.Where(a => a.Type.Time.AddYears(1).ToString().Equals(DateTime.Now)).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1).ToString().Equals(DateTime.Now)).ToList()); + + g.sqlserver.Insert(new Topic()).ExecuteAffrows(); + foreach (var dt in new[] { DateTime.Parse("2020-5-6 0:1:2"), DateTime.Parse("2020-11-16 13:21:22"), }) + { + Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm:ss.fff"), select.First(a => dt.ToString())); + Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm:ss"), select.First(a => dt.ToString("yyyy-MM-dd HH:mm:ss"))); + Assert.Equal(dt.ToString("yyyy-MM-dd HH:mm"), select.First(a => dt.ToString("yyyy-MM-dd HH:mm"))); + Assert.Equal(dt.ToString("yyyy-MM-dd HH"), select.First(a => dt.ToString("yyyy-MM-dd HH"))); + Assert.Equal(dt.ToString("yyyy-MM-dd"), select.First(a => dt.ToString("yyyy-MM-dd"))); + Assert.Equal(dt.ToString("yyyy-MM"), select.First(a => dt.ToString("yyyy-MM"))); + Assert.Equal(dt.ToString("yyyyMMdd"), select.First(a => dt.ToString("yyyyMMdd"))); + Assert.Equal(dt.ToString("yyyyMM"), select.First(a => dt.ToString("yyyyMM"))); + Assert.Equal(dt.ToString("yyyy"), select.First(a => dt.ToString("yyyy"))); + Assert.Equal(dt.ToString("HH:mm:ss"), select.First(a => dt.ToString("HH:mm:ss"))); + 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"))); + } + } [Fact] public void Now() { @@ -277,14 +302,6 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => a.Type.Time.AddYears(1).Equals(DateTime.Now)).ToList()); data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1).Equals(DateTime.Now)).ToList()); } - [Fact] - public void this_ToString() - { - var data = new List(); - data.Add(select.Where(a => a.CreateTime.ToString().Equals(DateTime.Now)).ToList()); - data.Add(select.Where(a => a.Type.Time.AddYears(1).ToString().Equals(DateTime.Now)).ToList()); - data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1).ToString().Equals(DateTime.Now)).ToList()); - } [Fact] public void DateTime_Compare() diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs index 280a6181..d8f7dc9b 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs @@ -1,11 +1,10 @@ 锘縰sing FreeSql.Internal; -using FreeSql.Internal.Model; using System; using System.Collections; -using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.Odbc.SqlServer { @@ -374,7 +373,49 @@ namespace FreeSql.Odbc.SqlServer break; case "Equals": return $"({left} = {args1})"; case "CompareTo": return $"datediff(second,{args1},{left})"; - case "ToString": return exp.Arguments.Count == 0 ? $"convert(varchar, {left}, 121)" : null; + case "ToString": + if (exp.Arguments.Count == 0) return $"convert(varchar, cast({left} as datetime), 121)"; + left = $"cast({left} as datetime)"; + switch (args1.TrimStart('N')) + { + case "'yyyy-MM-dd HH:mm:ss'": return $"convert(char(19), {left}, 120)"; + case "'yyyy-MM-dd HH:mm'": return $"substring(convert(char(19), {left}, 120), 1, 16)"; + case "'yyyy-MM-dd HH'": return $"substring(convert(char(19), {left}, 120), 1, 13)"; + case "'yyyy-MM-dd'": return $"convert(char(10), {left}, 23)"; + case "'yyyy-MM'": return $"substring(convert(char(10), {left}, 23), 1, 7)"; + case "'yyyyMMdd'": return $"convert(char(8), {left}, 112)"; + case "'yyyyMM'": return $"substring(convert(char(8), {left}, 112), 1, 6)"; + case "'yyyy'": return $"substring(convert(char(8), {left}, 112), 1, 4)"; + case "'HH:mm:ss'": return $"convert(char(8), {left}, 24)"; + } + var nchar = args1.StartsWith("N'") ? "N" : ""; + return Regex.Replace(args1, "(yyyy|yy|MM|M|dd|d|HH|H|hh|h|mm|m|ss|s|tt|t)", m => + { + switch (m.Groups[1].Value) + { + case "yyyy": return $"' + substring(convert(char(8), {left}, 112), 1, 4) + {nchar}'"; + case "yy": return $"' + substring(convert(char(6), {left}, 12), 1, 2) + {nchar}'"; + case "MM": return $"' + substring(convert(char(6), {left}, 12), 3, 2) + {nchar}'"; + case "M": return $"' + case when substring(convert(char(6), {left}, 12), 3, 1) = '0' then substring(convert(char(6), {left}, 12), 4, 1) else substring(convert(char(6), {left}, 12), 3, 2) end + {nchar}'"; + case "dd": return $"' + substring(convert(char(6), {left}, 12), 5, 2) + {nchar}'"; + case "d": return $"' + case when substring(convert(char(6), {left}, 12), 5, 1) = '0' then substring(convert(char(6), {left}, 12), 6, 1) else substring(convert(char(6), {left}, 12), 5, 2) end + {nchar}'"; + case "HH": return $"' + substring(convert(char(8), {left}, 24), 1, 2) + {nchar}'"; + case "H": return $"' + case when substring(convert(char(8), {left}, 24), 1, 1) = '0' then substring(convert(char(8), {left}, 24), 2, 1) else substring(convert(char(8), {left}, 24), 1, 2) end + {nchar}'"; + case "hh": + return $"' + case cast(case when substring(convert(char(8), {left}, 24), 1, 1) = '0' then substring(convert(char(8), {left}, 24), 2, 1) else substring(convert(char(8), {left}, 24), 1, 2) end as int) % 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 + {nchar}'"; + case "h": + return $"' + case cast(case when substring(convert(char(8), {left}, 24), 1, 1) = '0' then substring(convert(char(8), {left}, 24), 2, 1) else substring(convert(char(8), {left}, 24), 1, 2) end as int) % 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 + {nchar}'"; + case "mm": return $"' + substring(convert(char(8), {left}, 24), 4, 2) + {nchar}'"; + case "m": return $"' + case when substring(convert(char(8), {left}, 24), 4, 1) = '0' then substring(convert(char(8), {left}, 24), 5, 1) else substring(convert(char(8), {left}, 24), 4, 2) end + {nchar}'"; + case "ss": return $"' + substring(convert(char(8), {left}, 24), 7, 2) + {nchar}'"; + case "s": return $"' + case when substring(convert(char(8), {left}, 24), 7, 1) = '0' then substring(convert(char(8), {left}, 24), 8, 1) else substring(convert(char(8), {left}, 24), 7, 2) end + {nchar}'"; + case "tt": return $"' + case when cast(case when substring(convert(char(8), {left}, 24), 1, 1) = '0' then substring(convert(char(8), {left}, 24), 2, 1) else substring(convert(char(8), {left}, 24), 1, 2) end as int) >= 12 then 'PM' else 'AM' end + {nchar}'"; + case "t": return $"' + case when cast(case when substring(convert(char(8), {left}, 24), 1, 1) = '0' then substring(convert(char(8), {left}, 24), 2, 1) else substring(convert(char(8), {left}, 24), 1, 2) end as int) >= 12 then 'P' else 'A' end + {nchar}'"; + } + return m.Groups[0].Value; + }); } } return null; diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs index 4abd09ac..b4b7c563 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs @@ -1,11 +1,10 @@ 锘縰sing FreeSql.Internal; -using FreeSql.Internal.Model; using System; using System.Collections; -using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; +using System.Text.RegularExpressions; namespace FreeSql.SqlServer { @@ -374,7 +373,47 @@ namespace FreeSql.SqlServer break; case "Equals": return $"({left} = {args1})"; case "CompareTo": return $"datediff(second,{args1},{left})"; - case "ToString": return exp.Arguments.Count == 0 ? $"convert(varchar, {left}, 121)" : null; + case "ToString": + if (exp.Arguments.Count == 0) return $"convert(varchar, cast({left} as datetime), 121)"; + left = $"cast({left} as datetime)"; + switch (args1.TrimStart('N')) + { + case "'yyyy-MM-dd HH:mm:ss'": return $"convert(char(19), {left}, 120)"; + case "'yyyy-MM-dd HH:mm'": return $"substring(convert(char(19), {left}, 120), 1, 16)"; + case "'yyyy-MM-dd HH'": return $"substring(convert(char(19), {left}, 120), 1, 13)"; + case "'yyyy-MM-dd'": return $"convert(char(10), {left}, 23)"; + case "'yyyy-MM'": return $"substring(convert(char(10), {left}, 23), 1, 7)"; + case "'yyyyMMdd'": return $"convert(char(8), {left}, 112)"; + case "'yyyyMM'": return $"substring(convert(char(8), {left}, 112), 1, 6)"; + case "'yyyy'": return $"substring(convert(char(8), {left}, 112), 1, 4)"; + case "'HH:mm:ss'": return $"convert(char(8), {left}, 24)"; + } + var nchar = args1.StartsWith("N'") ? "N" : ""; + return Regex.Replace(args1, "(yyyy|yy|MM|M|dd|d|HH|H|hh|h|mm|m|ss|s|tt|t)", m => + { + switch (m.Groups[1].Value) + { + case "yyyy": return $"' + substring(convert(char(8), {left}, 112), 1, 4) + {nchar}'"; + case "yy": return $"' + substring(convert(char(6), {left}, 12), 1, 2) + {nchar}'"; + case "MM": return $"' + substring(convert(char(6), {left}, 12), 3, 2) + {nchar}'"; + case "M": return $"' + case when substring(convert(char(6), {left}, 12), 3, 1) = '0' then substring(convert(char(6), {left}, 12), 4, 1) else substring(convert(char(6), {left}, 12), 3, 2) end + {nchar}'"; + case "dd": return $"' + substring(convert(char(6), {left}, 12), 5, 2) + {nchar}'"; + case "d": return $"' + case when substring(convert(char(6), {left}, 12), 5, 1) = '0' then substring(convert(char(6), {left}, 12), 6, 1) else substring(convert(char(6), {left}, 12), 5, 2) end + {nchar}'"; + case "HH": return $"' + substring(convert(char(8), {left}, 24), 1, 2) + {nchar}'"; + case "H": return $"' + case when substring(convert(char(8), {left}, 24), 1, 1) = '0' then substring(convert(char(8), {left}, 24), 2, 1) else substring(convert(char(8), {left}, 24), 1, 2) end + {nchar}'"; + case "hh": return $"' + case cast(case when substring(convert(char(8), {left}, 24), 1, 1) = '0' then substring(convert(char(8), {left}, 24), 2, 1) else substring(convert(char(8), {left}, 24), 1, 2) end as int) % 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 + {nchar}'"; + case "h": return $"' + case cast(case when substring(convert(char(8), {left}, 24), 1, 1) = '0' then substring(convert(char(8), {left}, 24), 2, 1) else substring(convert(char(8), {left}, 24), 1, 2) end as int) % 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 + {nchar}'"; + case "mm": return $"' + substring(convert(char(8), {left}, 24), 4, 2) + {nchar}'"; + case "m": return $"' + case when substring(convert(char(8), {left}, 24), 4, 1) = '0' then substring(convert(char(8), {left}, 24), 5, 1) else substring(convert(char(8), {left}, 24), 4, 2) end + {nchar}'"; + case "ss": return $"' + substring(convert(char(8), {left}, 24), 7, 2) + {nchar}'"; + case "s": return $"' + case when substring(convert(char(8), {left}, 24), 7, 1) = '0' then substring(convert(char(8), {left}, 24), 8, 1) else substring(convert(char(8), {left}, 24), 7, 2) end + {nchar}'"; + case "tt": return $"' + case when cast(case when substring(convert(char(8), {left}, 24), 1, 1) = '0' then substring(convert(char(8), {left}, 24), 2, 1) else substring(convert(char(8), {left}, 24), 1, 2) end as int) >= 12 then 'PM' else 'AM' end + {nchar}'"; + case "t": return $"' + case when cast(case when substring(convert(char(8), {left}, 24), 1, 1) = '0' then substring(convert(char(8), {left}, 24), 2, 1) else substring(convert(char(8), {left}, 24), 1, 2) end as int) >= 12 then 'P' else 'A' end + {nchar}'"; + } + return m.Groups[0].Value; + }); } } return null;