Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Foxpro/Clipper/Dbase > Разность дат


Автор: nitr 3.6.2007, 23:02
Уважаемые, столкнулся с такой задачкой (я в фокспро только по хелпам ориентируюсь smile ):
мне надо определить возраст человека в годах от конкретной даты, т.е. к примеру, человек несовершеннолетний. В SQL мне просто, а в Фоксе не смог аналоги функций найти...
Вот как это выглядит (один из вариантов) в SQL DATEADD(YEAR, -18, '2007.31.05') >= born_date, т.е. вычитает 18 лет от конкретной даты (не просто 2007-18, а календарных) и сравниваем с датой рождения.

Добавлено @ 12:16
Вот уточняю в чем загвоздка:
если человек родился 05.06.2000 , а отчет ведётся от 01.01.2007, то ему не 7 лет smile , а будет только 5 июня smile

Заранее благодарю за помощь!

P.S.: если что-то не до конца объяснил, извини, спрашивайте, уточню.

Автор: nitr 3.6.2007, 23:24
есть одна мысль, но как-то страшно от погрешностей (високосные года)
Код

SELECT * FROM MyTab WHERE (our_date - born_date)/365.25 < 18

есть др. варианты с учетом високсных...?

Автор: Данкинг 3.6.2007, 23:35
Код

? YEAR(DATE())-YEAR(dat)

Показывает разницу между сегодняшней датой (date() ) и датой рождения (dat - переменная или поле в таблице).

Автор: nitr 3.6.2007, 23:35
вот ещё нашел (но так же не определяет високсные :( ):
Код

SELECT * FROM MyTab WHERE born_date > GOMONTH(our_date, -216)

жду от вас вариантов smile

Автор: Данкинг 3.6.2007, 23:38
GOMONTH - я такой функции не знал даже. smile Сейчас почитал хелп - всё равно не врубился.

Автор: nitr 3.6.2007, 23:40
Данкинг, данная ф-ция считает високосные?

Автор: Данкинг 3.6.2007, 23:45
Не знаю, не пробовал! smile Попробуй - расскажешь! Но, по идее, должна, а почему нет? Иначе на кой она нужна вообще.

Автор: nitr 3.6.2007, 23:57
smile я имел ввиду, принимает ли високосные года в этой разности? Вот уточняю в чем загвоздка:
если человек родился 05.06.2000 , а отчет ведётся от 01.01.2007, то ему не 7 лет smile , а будет только 5 июня smile

P.S.: немного сам уже запутался, но сейчас уже уточнил, т.е. считать надо днями...

Добавлено через 58 секунд
если же перегонять в дни обычными математическими способами, то ошибка или погрешность, т.к. есть високосные...

Автор: Cashey 6.6.2007, 13:50
а причем тут високосные года при такой задачи? в задаче же достаточно просто поменять год, оставив в силе день и месяц. или не понятна задача

Автор: nitr 6.6.2007, 21:04
Cashey, согласен, я тоже оп "первости" так и ответил. Меня попросили узнать... позже в вопросе я написал уточнение... Повторюсь:
надо определить возраст от определённой даты, т.е. известны две даты.
Как пример:
  дата отсчета - 31.05.2007
  дата ДР          - 30.11.1989
Если мы вычтим год, то получаем ему 18 лет, ну а реально видно что нет. Cashey, вы предлагаете сохранять, не понял для чего, уточните.

Единственное решение, которым я помог человеку, тоже указал
Код

SELECT * FROM MyTab WHERE (our_date - born_date)/365.25 < 18

т.е. в разности у нас количество дней, делим на среднее (365+365+365+366)/4, простое решение, но думал есть более распространненые решения.

Извиняюсь, если повторно не смог объяснить суть вопроса.

Автор: Cashey 7.6.2007, 09:16
Цитата(nitr @  6.6.2007,  22:04 Найти цитируемый пост)
Повторюсь:
надо определить возраст от определённой даты, т.е. известны две даты.
Как пример:
  дата отсчета - 31.05.2007
  дата ДР          - 30.11.1989
Если мы вычтим год, то получаем ему 18 лет, ну а реально видно что нет. Cashey, вы предлагаете сохранять, не понял для чего, уточните.

Вы хотите сказать, что если человек родился 01.01.2000 года то 01.01.2018 (пройдет 5 високосных года), то его не признают совершеннолетним?

ну ладно, хотите точно, будет вам точно. разность дат возвращает кол-во дней с учетом високостности
т.е.
Код

?CTOD('01.01.2000')-CTOD('01.01.2001')

вернет 366 дней, а
Код

?CTOD('01.01.2001')-CTOD('01.01.2002')

вернет 365 дней
таким образом, можно определить количество дней до 18 лет (по вашему мнению) на момент формирования отчета. т.е.
Код

?CTOD('31.05.2007')-CTOD('31.05.'+ltRIM(STR(YEAR(CTOD('31.05.2007'))-18)))

вернет вам количество дней (с учетом високосности) между 31.05.07 и 31.05, 18 лет назад.
и соответсвенно
Код

SELECT * FROM MyTab WHERE born_date <  our_date-CTOD(LEFT(dtoc(our_date),6) + ltRIM(STR(YEAR(our_date)-18)))

сделает выборку по всем лицам моложе 18 календарных дней (с учетом високостности)
если же очень хочется принимать за год строго 365 дней то
Код

?CTOD('01.05.2007')-(18*365)

и тогда 
Код

SELECT * FROM MyTab WHERE born_date < our_date-(18*365) 


или же я что-то упорно не могу понять.....

Добавлено через 4 минуты и 12 секунд
все расчеты проводились при установке 
Код

SET DATE GERMAN

Автор: nitr 7.6.2007, 23:16
Cashey, я же привел точный пример smile Вы выбрали "очень удобные даты". Я вам указал:
Цитата

  дата отсчета - 31.05.2007
  дата ДР          - 30.11.1989


Я выше указал свой пример с разностью ДАТ, и сказал, что получаем дни, вот и просил др. способы, которые дали бы ответ без погрешностей. Я сейчас не смогу показть при каких датах может быть необходим високосный год, но согласитесь, такое возможно, т.к. ДАТА1-ДАТА2 (в Фоксе) это ДНИ, даже если есть учёт вискоскных, а нужен возраст в "летах".

Моё решение по определению возраста от определ. даты (но с погрешностью) (ДАТА1-ДАТА2)/365.25, просто расчитывал, что есть что-то иное.

Спасибо всем!!! Благодарю.

Автор: Cashey 8.6.2007, 12:32
nitr, я специально выбрал даты включающие и не включающие високосные года

Цитата(nitr @  8.6.2007,  00:16 Найти цитируемый пост)
 
дата отсчета - 31.05.2007
дата ДР          - 30.11.1989

ну и что тут не так?
сколько по вашему должно быть лет человеку с датой рождения 30.11.1989 когда наступит 31.05.2007 и 30.11.2007?
и потом, что вам нужно в итоге? сделать выборку всех лиц у которых на дату Х не исполнилось полных 18 лет? тогда мой запрос
Цитата(Cashey @  7.6.2007,  10:16 Найти цитируемый пост)
SELECT * FROM MyTab WHERE born_date <  our_date-CTOD(LEFT(dtoc(our_date),6) + ltRIM(STR(YEAR(our_date)-18)))

если хотите получить только количество полных лет между 2-мя датами
тогда так:
Код

d1 = '31.05.2007'
d2 = '30.11.1989'
*определяем разницу лет
y1 = YEAR(CTOD(d1))-YEAR(CTOD(d2))
*определяем разницу дней в одном году
d3 = CTOD(d2) - CTOD('01.01.' + RIGHT(d2,4))
d4 = CTOD(LEFT(d1,6)+RIGHT(d2,4)) - CTOD('01.01.' + RIGHT(d2,4))
IF d4<d3 && и еслиполных лет еще нет, то минус один год
    ? y1-1
ELSE
    ?y1
ENDIF


Цитата(nitr @  8.6.2007,  00:16 Найти цитируемый пост)
Моё решение по определению возраста от определ. даты (но с погрешностью) (ДАТА1-ДАТА2)/365.25, просто расчитывал, что есть что-то иное.

Это решение несколько не точное. Ну как вы собираетесь определять полное количество лет? Взяв только целую часть от полученной дроби? Тогда посмотрите сколько лет получится при датах 
отчета '30.11.2007' и даты рождения '30.11.1989'.

Автор: nitr 8.6.2007, 14:02
Спасибо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)