【问题标题】:Date calculations with sqlite3使用 sqlite3 计算日期
【发布时间】:2026-02-11 20:20:10
【问题描述】:

我正在尝试计算日期之间的时间跨度。如果日期使用原生 sqlite3 格式 'YYYY-dd-mm' 格式化,我对此没有任何问题

如果日期格式不同,例如“dd-mm-YYYY”,我该怎么做

我尝试了以下但没有成功。

--选择两天之间的天数;如果日期时间字符串的格式为 YYYY-dd-mm

,则此方法有效
SELECT julianday(date1) - julianday(date2) AS Span from myTable;

--我尝试了 dd-mm-YYYY 格式的日期,但它似乎不起作用 --好像不能指定日期格式。

SELECT julianday(strftime('%d-%m-%Y', date1)) - julianday(strftime('%d-%m-%Y', date2)) AS Span from myTable;

【问题讨论】:

    标签: sql sqlite system.data.sqlite


    【解决方案1】:

    由于您使用的是 System.Data.SQLite,我建议您使用自定义函数。这将更易于使用并与 MS SQL Server 保持一致,从而使其他 .NET 开发人员更易于理解和维护。

    /// <summary>
    /// MS SQL 2005 Compatible DateDiff() function.
    /// </summary>
    /// <remarks>
    /// ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.SQL.v2005.en/tsqlref9/html/eba979f2-1a8d-4cce-9d75-b74f9b519b37.htm
    /// 
    /// 
    /// </remarks>
    [SQLiteFunction(Name = "DateDiff", Arguments = 3, FuncType = FunctionType.Scalar)]
    public class DateDiff : SQLiteFunction
    {
        public override object Invoke(object[] args)
        {
            if (args[0] == DBNull.Value || 
                args[1] == DBNull.Value ||
                args[2] == DBNull.Value)
            {
                return null;
            }
            string part = Convert.ToString(args[0]);
            DateTime startTime = ToDateTime(args[1]);
            DateTime endTime = ToDateTime(args[2]);
    
            switch(part)
            {
                case "year":
                case "yy":
                case "yyyy":
                    return endTime.Year - startTime.Year;
    
                case "quarter":
                case "qq":
                case "q":
                    return (endTime.Year - startTime.Year) * 4 + ((endTime.Month - 1) / 3) - ((startTime.Month - 1) / 3);
    
                case "month":
                case "mm":
                case "m":
                    return (endTime.Year - startTime.Year) * 12 + endTime.Month - startTime.Month;
    
                case "dayofyear":
                case "dy":
                case "y":
                case "day":
                case "dd":
                case "d":
                    return (endTime - startTime).TotalDays;
    
                case "week":
                case "wk":
                case "ww":
                    return (endTime - startTime).TotalDays / 7.0;
    
                case "Hour":
                case "hh":
                case "h":
                    return (endTime - startTime).TotalHours;
    
                case "minute":
                case "mi":
                case "n":
                    return (endTime - startTime).TotalMinutes;
    
                case "second":
                case "ss":
                case "s":
                    return (endTime - startTime).TotalSeconds;
    
                case "millisecond":
                case "ms":
                    return (endTime - startTime).TotalMilliseconds;
    
                default:
                    throw new ArgumentException(String.Format("Date part '{0}' is not recognized.", part));
            }
    
        }
    
        private static DateTime ToDateTime(object source)
        {
            try
            {
                return Convert.ToDateTime(source);              
            } 
            catch (Exception ex)
            {
                throw new ArgumentException(String.Format("DateDiff Input value '{0}' can not be converted to a DateTime.", source), ex);
            }
        }
    }
    

    【讨论】:

    • 我最终通过导出表格、将日期列格式更改为原生 sqlite3 格式然后重新导入表格来解决问题。但是,我确实喜欢这种方法,并且我认为实施并测试它。我会带着结果回来。
    • 不幸的是,为了使其工作,您需要将第一个参数作为字符串传递。例如:datediff('mi',date2,date1),但在 SQL Server 中,您需要不带引号传递它,例如 datediff(mi,date2,date1)
    • @NYCChris,很好,这个 SQLite 版本使用字符串,MSSQL 函数使用 datepart 常量。我不知道有什么方法可以复制 SQLite 中的常量。