Мне нужно написать функцию, которая получает два аргумента startdate и enddate, где она возвращает разницу между этими двумя датами.
Скажите, что эта функция monthfractiondiff(startdate,enddate)
например monthfractiondiff(15/01/2016,15/02/2016) вернется
((31-15)/31)+(15/29) = 1.0333704116
monthfractiondiff(15/11/2018,15/02/2019) вернется
((30-15)/30)+1+1+(15/28) = 3.0357142857
Я тщетно пытался https://access-programmers.co.uk/forums/showthread.php?t=113589
@FreeMan Я пробовал приведенный выше код (опубликованный pstraton), он работает, когда даты начала и окончания приходятся на один и тот же год, но происходит не так, когда обе даты приходятся на разные годы, например. Дата начала в 2018 году и дата окончания в 2019 году.
Посмотрите ветку, которую вы упоминаете, прокрутите вниз и попробуйте код пользователя пстратон.
Спасибо за ответ. обновил свой комментарий. Действительно ли это работает?





ОБНОВЛЕНО благодаря другому ответу WeeBee
Function HowManyMonths(startdate As Date, Enddate As Date) As Double
Dim pctSTARTmonth As Double, pctENDmonth As Double, M As Long
'caputues percentage of month
pctSTARTmonth = Day(startdate) / Day(DateSerial(Year(startdate), Month(startdate) + 1, 1) - 1)
pctENDmonth = Day(Enddate) / Day(DateSerial(Year(Enddate), Month(Enddate) + 1, 1) - 1)
'Use Date difference function to get whole number and then combine perc
HowManyMonths = DateDiff("M", startdate, Enddate) + pctENDmonth - pctSTARTmonth
End Function
Спасибо! но он также не вычисляет правильную часть месяца, например. HowManyMonths(03 декабря 2018 г., 17 июня 2019 г.) возвращает 6.5032, что было бы 29/31+1+1+1+1+1+17/30 = 6.50215053762 or 6.5022
@SIslam, это другой подход, чем то, что вы говорили ранее. В вашем первом примере с ноябрем вы вычли дату из общего числа дней, разделенную на общее количество дней, поэтому: (30-15)/30=0.5. Но с вашим примером от 3 декабря вы показываете 29/31, что является другим подходом. Основываясь на вашем предыдущем примере, это будет равно 28, вместо этого вы 31-2 получите 29 вместо 31. Это объясняет вашу разницу. Если вы хотите указать дату начала (как вы сделали для декабрьских примеров), ее легко изменить.
monthfractiondiff(15/01/2016,15/02/2016) will return ((31-15)/31)+(15/29) = 1.0333704116 Здесь (31-15) = (Total Days in that month)-Day portion of the start date@SIslam извините, я не понимаю. Удачи с этим.
Извините, если вы не понимаете. monthfractiondiff(15/01/2016,15/02/2016) вернётся ((31-15)/31)+(15/29) = 1.0333704116 Сюда (31-15) = (Total Days in January month)-(Day portion of the start date i.e. 15)
Да, я вижу, что... с 15 января по 15 февраля в високосный год равно 1,0337 (31-15) = 16/31 + 15/29. Это то, что возвращает моя формула, и это то, что вы указали в качестве ожидаемого результата в своем примере. . Это не тот же подход в вашем примере от 3 декабря, который = (31-3) = показывает ДВАДЦАТЬ ДЕВЯТЬ вместо 28, разделенных на 31.
Я бы пошел с datediff().
datediff("d", "01/01/2019", date())/30.5
Сегодня это возвращает мне 4 85245901639344.
Мне больше нравится ваш общий подход (т. е. стандартизация месяца), но ОП ясно дает понять, что он / она ищет каждый месяц для преобразования в процент в относительных днях месяца. Ваша формула не совсем подходит, так как она вернет 1,0163 для примера января/февраля вместо 1,0337.
Да, у моей формулы нет твоего уровня точности, это математический подход.
Я украл часть вашего ответа (и заплатил за это кликом вверх!). DateDiff — лучший подход, чем моя идея цикла.
Спасибо, @PGCodeRider!
Поскольку количество дней в месяцах варьируется, вы должны считать по дням, чтобы получить как можно более точное значение, поскольку никогда (кроме как в течение месяца или в течение июля/августа или декабря/января) не будет точного значения:
' Rounds by default to two decimals, as more decimals has no meaning
' due to the varying count of days of a month.
' Optionally, don't round, by setting Round2 to False.
'
Public Function TotalMonths( _
ByVal Date1 As Date, _
ByVal Date2 As Date, _
Optional Round2 As Boolean = True) _
As Double
Dim Months As Double
Dim Part1 As Double
Dim Part2 As Double
Dim Fraction As Double
Dim Result As Double
Months = DateDiff("m", Date1, Date2)
Part1 = (Day(Date1) - 1) / DaysInMonth(Date1)
Part2 = (Day(Date2) - 1) / DaysInMonth(Date2)
If Round2 = True Then
' Round to two decimals.
Fraction = (-Part1 + Part2) * 100
Result = Months + Int(Fraction + 0.5) / 100
Else
Result = Months - Part1 + Part2
End If
TotalMonths = Result
End Function
' Returns the count of days of the month of Date1.
'
' 2016-02-14. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function DaysInMonth( _
ByVal Date1 As Date) _
As Integer
Const MaxDateValue As Date = #12/31/9999#
Const MaxDayValue As Integer = 31
Dim Days As Integer
If DateDiff("m", Date1, MaxDateValue) = 0 Then
Days = MaxDayValue
Else
Days = Day(DateSerial(Year(Date1), Month(Date1) + 1, 0))
End If
DaysInMonth = Days
End Function
Результаты:
? TotalMonths(#2016/01/15#, #2016/02/15#)
1.03
? TotalMonths(#2018/11/15#, #2019/02/15#)
3.03
Кажется, довольно много усилий, чтобы получить DaysInMonth. Смотрите мой подход ниже: Day(DateSerial(Year(startdate), Month(startdate) + 1, 1) - 1)
@PGCodeRider: взято из структурированной библиотеки.
Опубликуйте фактический код, который вы пробовали, и укажите, какая его часть работает неправильно. «Тщетно пытался» может быть опечаткой в том, что вы перепечатали, может быть, вы пропустили строку при копировании/вставке, трудно сказать...