Типичные примитивные типы .NET не имеют общего интерфейса, который позволяет использовать их для вычислений. Можно было бы определить ваши собственные интерфейсы (например, ISignedWholeNumber
), которые будут выполнять такие операции, определять структуры, которые содержат один Int16
, Int32
и т. Д., И реализовывать эти интерфейсы, а затем использовать методы, которые принимают общие типы ограничено ISignedWholeNumber
, но для преобразования числовых значений в типы структуры, вероятно, будет неприятность.
Альтернативным подходом было бы определить статический класс Int64Converter<T>
со статическим свойством bool Available {get;};
и статическим делегаты для Int64 GetInt64(T value)
, T FromInt64(Int64 value)
, bool TryStoreInt64(Int64 value, ref T dest)
. Конструктор класса может быть жестко закодирован для загрузки делегатов для известных типов и, возможно, использовать Reflection для проверки того, реализует ли тип T
методы с собственными именами и сигнатурами (в случае, если это что-то вроде структуры, которая содержит Int64
и представляет собой число, но имеет собственный метод ToString()
). Такой подход потеряет преимущества, связанные с проверкой типа времени компиляции, но все равно удастся избежать операций в боксе, и каждый тип нужно будет только «проверять» один раз. После этого операции, связанные с этим типом, будут заменены диспетчером делегатов.
Можно использовать следующее с первым днем указанного месяца:
datediff(day, @date, dateadd(month, 1, @date))
Заставить его работать на каждую дату:
datediff(day, dateadd(day, 1-day(@date), @date),
dateadd(month, 1, dateadd(day, 1-day(@date), @date)))
Я upvoted Mehrdad, но это работает также.:)
CREATE function dbo.IsLeapYear
(
@TestYear int
)
RETURNS bit
AS
BEGIN
declare @Result bit
set @Result =
cast(
case when ((@TestYear % 4 = 0) and (@testYear % 100 != 0)) or (@TestYear % 400 = 0)
then 1
else 0
end
as bit )
return @Result
END
GO
CREATE FUNCTION dbo.GetDaysInMonth
(
@TestDT datetime
)
RETURNS INT
AS
BEGIN
DECLARE @Result int
DECLARE @MonthNo int
Set @MonthNo = datepart(m,@TestDT)
Set @Result =
case @MonthNo
when 1 then 31
when 2 then
case
when dbo.IsLeapYear(datepart(yyyy,@TestDT)) = 0
then 28
else 29
end
when 3 then 31
when 4 then 30
when 5 then 31
when 6 then 30
when 7 then 31
when 8 then 31
when 9 then 30
when 10 then 31
when 11 then 30
when 12 then 31
end
RETURN @Result
END
GO
Протестировать
declare @testDT datetime;
set @testDT = '2404-feb-15';
select dbo.GetDaysInMonth(@testDT)
вот другой...
Select Day(DateAdd(day, -Day(DateAdd(month, 1, getdate())),
DateAdd(month, 1, getdate())))
--Last Day of Previous Month
SELECT DATEPART(day, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)))
--Last Day of Current Month
SELECT DATEPART(day, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0)))
--Last Day of Next Month
SELECT DATEPART(day, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+2,0)))
Лично, хотя, я сделал бы UDF для него, если нет созданного в функции...
Действительно необходимо добавить функцию, но это - простое. Я использую это:
CREATE FUNCTION [dbo].[ufn_GetDaysInMonth] ( @pDate DATETIME )
RETURNS INT
AS
BEGIN
SET @pDate = CONVERT(VARCHAR(10), @pDate, 101)
SET @pDate = @pDate - DAY(@pDate) + 1
RETURN DATEDIFF(DD, @pDate, DATEADD(MM, 1, @pDate))
END
GO
RETURN day(dateadd(month, 12 * @year + @month - 22800, -1))
select day(dateadd(month, 12 * year(date) + month(date) - 22800, -1))