Форум » [x]Harbour » Високосный год » Ответить

Високосный год

Pasha: В качестве разминки, предложите алгоритм: Есть даты: d1 и d2 Как определить, попадает ли високосный день 29.02 в промежуток между d1 и d2 ?

Ответов - 11

PSP: Может так? [pre2] FOR i := Year(d1) to Year(d2) ? Empty( CDoW( "29.02." + AllTrim( Str( i, 4, 0 ) ) ) ) NEXT [/pre2]

Dima: Или можно заюзать Empty(Ctod ("29/02/2018")) // .T. От не существующей даты вернет .T. То есть тоже цикл но с d1 по d2

yury: определить високосный год Function IsLeapYear(nYEAR) RETURN IIF((nYEAR % 4 = 0 .AND. nYEAR % 100 <> 0) .OR. nYear % 400 = 0 ,.T.,.F.) определить количество дней в месяце Function DaysInMonth( nMonth, lLeapYear ) Local nRes DO CASE CASE nMonth = 2 nRes = IIF(lLeapYear,29,28) CASE nMonth = 4 .OR. nMonth = 6 .OR. nMonth = 9 .OR. nMonth = 11 nRes = 30 OTHERWISE nRes = 31 ENDCASE Return nRes


Pasha: В одну строку, увы, не получается, да и без цикла не обойтись В конце концов, вышел такой вариант: [pre2]Function DatesLeap(d1, d2) Local lleap := .f., nY1, nY2, nY if ! Empty(d1) .and. ! Empty(d2) .and. d1 <= d2 if Month(d2) == 2 .and. Day(d2) == 29 lLeap := .t. else nY1 := Year(d1) if Month(d1) >= 3 nY1 ++ endif nY2 := Year(d2) if Month(d2) <= 2 nY2 -- endif for nY := nY1 to nY2 if ( ( nY % 4 ) == 0 .and. ( nY % 100 ) != 0 ) .or. ( nY % 400 == 0 ) lLeap := .t. exit endif next endif endif Return lLeap [/pre2]

Dima: Pasha пишет: В одну строку, увы, не получается, да и без цикла не обойтись а так , или я задачу не понял ? [pre2] set date to german a:=ctod("20.02.2016") b:=ctod("20.02.2017") c:=ctod("29.02.2016") ? test(a,b,c) Func Test(d1,d2,vd) return vd>=d1 .and. vd<=d2 [/pre2]

Pasha: Заданы a и b (d1 и d2), а c - нет.

Петр: Моя версия [pre2] #include "assert.ch" local d1, d2, dim set date format to "dd.mm.yyyy" d1 := ctod("20.02.2023") d2 := ctod("20.02.2016") dim := DatesLeap( d1, d2 ) ASSERT( ! Empty( dim ), "dates not found" ) Aeval( dim, {|e|Qout( e )} ) return proc DatesLeap( d1, d2 ) local a := min( d1, d2 ) local b := max( d1, d2 ) local dim := {} for i := year( a ) to year( b ) c := ctod( "29.02." + str( i, 4 ) ) if /* ! Empty( c ) .and. */ Between( c, a, b ) AAdd( dim, c ) endif next return dim[/pre2]

Петр: Between - это из foxpro (hbfoxpro), удобная вещь [pre2] #pragma BEGINDUMP #include "hbapi.h" #include "hbapiitm.h" HB_FUNC( BETWEEN ) { HB_BOOL fResult = HB_FALSE; if( hb_pcount() == 3 ) { PHB_ITEM pItem = hb_param( 1, HB_IT_ANY ); int iResult1, iResult2; if( hb_itemCompare( pItem, hb_param( 12, HB_IT_ANY ), HB_FALSE, &iResult1 ) && hb_itemCompare( pItem, hb_param( 23, HB_IT_ANY ), HB_FALSE, &iResult2 ) ) fResult = iResult1 >= 0 && iResult2 <= 0; } hb_retl( fResult ); } #pragma ENDDUMP[/pre2] Оп-па! Попался..

Петр: Определяет, лежит ли значение некоторого выражения в диапазоне между значениями двух других выражений, имеющих тот же тип данных. Синтаксис: BETWEEN(eTestValue, eLowValue, eHighValue) Параметры: eTestValue Задает выражение, значение которого проверяет функция BETWEEN( ). Если значение выражения eTestValue больше или равно значению выражения eLowerValue и меньше или равно значению выражения eHighValue, функция BETWEEN( ) возвращает значение "истина" (.T.). В противном случае BETWEEN( ) возвращает "ложь" (.F.). BETWEEN( ) возвращает значение NULL, если значением eLowValue или eHighValue является NULL. eLowValue Задает нижнюю границу диапазона, проверяемого функцией BETWEEN( ). eHighValue Задает верхнюю границу диапазона, проверяемого функцией BETWEEN( ). Таки косяк.

tbolt: Еще один велосипед, конечно, здорово. Dima, таки, прав! Вот эта функция дает такой же результат, что и DatesLeap от Pasha Без циклов и короче. [pre2]Function DatesLeap1( d1, d2 ) local lLeap := .F. local dat := stod( '20160229' ) if ! Empty( d1 ) .and. ! Empty( d2 ) .and. d1 <= d2 if d1 <= dat .and. dat <= d2 lLeap := .T. endif endif return lLeap [/pre2] Проверено на d1 := stod( '20160220' ) d2 := stod( '20160320' ) ? DatesLeap( d1, d2 ) ? DatesLeap1( d1, d2 ) wait d1 := stod( '20150220' ) d2 := stod( '20160229' ) ? DatesLeap( d1, d2 ) ? DatesLeap1( d1, d2 ) wait d1 := stod( '20160229' ) d2 := stod( '20160320' ) ? DatesLeap( d1, d2 ) ? DatesLeap1( d1, d2 ) wait d1 := stod( '20160329' ) d2 := stod( '20160520' ) ? DatesLeap( d1, d2 ) ? DatesLeap1( d1, d2 ) wait

Pasha: Вот эта функция дает такой же результат, что и DatesLeap от Pasha Без циклов и короче. Так задача стояла найти не 29.2.2016, а любой високосный день в заданном периоде. Впрочем, задача уже решена. Есть не один рабочий вариант. Все спасибо.



полная версия страницы