При получении даты нужно чтобы к текущему мес. прибавлялось число.К примеру к Month прибавить число "3". .data DatYear db "%02d",0 DatMonth db "%02d",0 DatDay db "%02d",0 invoke GetLocalTime ,ADDR DATA MOVZX EAX,DATA.wYear invoke wsprintfA,ADDR Year,ADDR DatYear,eax PUSH EAX MOVZX EAX,DATA.wMonth invoke wsprintfA,ADDR Month,ADDR DatMonth,eax PUSH EAX MOVZX EAX,DATA.wDay invoke wsprintfA,ADDR Day,ADDR DatDay,eax
SystemTimeToFileTime, FileTimeToSystemTime? если руками, то хз где найти алгоритм, не самому же писать
Иногда приходиться...( А на счет SystemTimeToFileTime- FileTimeToSystemTime, при увеличения на несколько месяцов текущей даты какое число дней будешь умножать на число месяцев, 30-31-28? А если тупо добавлять к числу месяцев, без преобразования даты к сотням нс и без учета дней, то можно получить 31 день в феврале...(кто пытался скормить такую дату в базу данных смеяться не будет...) Проблема с этим алгоритмом дествительно неприятная, красивой реализации скорее всего нет...( У кого-нибудь есть какие-либо идеи?
?! В общем случае да, а конкретно для прибавки месяцев достаточно проверки результата на > 12 с коррекцией месяца и года. ... Хотя в общем случае это верно только для дат <= 28, а для вариаций 31-30-28 вроде как сама задача прибавления месяцев получается бессмысленно-неоднозначной
Такой пример есть, только на дельфях и не знаю, работает ли Код (Text): function DateSer(y,m,d: Integer): TDateTime; const mj: array[1..12] of Integer=(31,28,31,30,31,30,31,31,30,31,30,31); var add: Integer; begin while(true) do begin y:=y+(m-1) div 12; m:= (m-1) mod 12 +1; if m<=0 then begin Inc(m,12); Dec(y); end; if ((y mod 4 = 0) and ((y mod 100<>0) or (y mod 400=0))) and (m=2) then add:=1 //дополнительный день в феврале else add:=0; if (d>0) and (d<=(mj[m]+add)) then break; if d>0 then begin Dec(d,mj[m]+add); Inc(m); end else begin Inc(d,mj[m]+add); Dec(m); end; end; Result:=EncodeDate(y,m,d); end; Используется как: Код (Text): DecodeDate(Date,y,m,d); NewDate:=DateSer(y-4,m+254,d+1234);
вообще-то.. правда, а что требуется? прибавить опредленное число дней (ex. 2 месяца~60 дней), или именно месяцев без учета числа дней в каждом? если второе, то в чем вопрос?
Nouzui В том, что речь идет не просто о месяце, а о дате, т.е. год-месяц-число. Если текущая дата <= 28, то вопросов нет, т.к. она существует в любом месяце любого года. А вот если к 29 января или к 31 мая добавить 1 месяц, то получится ерунда, т.к. 29 февраля существует только в високосном году, а 31 июня - только в известном фильме ) Об этом собс-но уже сказал CodeTao
торможу, бывает.. впрчем, нужно просто разобраться, что именно требуется, ведь общепринятого стандарта на то как "увеличить число месяцев" не существует
leo Не совсем, существуют также различные отклонения вроде банковского месяца и суток, когда в месяце 30 дней и сутки длятся с 00:00 по 24:00 включительно. Но здесь вряд ли речь об этом
В этом случае и год равен 360 дням, интересно как они переводят астрономическую дату в банковскую... Я смотрю не у кого нет готовой реализации subj(алгоритм rmn должен работать, но delphi!, слишком общий случай и никакой оптимизации), посему выкладываю на суд присяжных следующий алгоритм, в нем сохраняется позиция дня от конца месяца(при небольшой модификации можно получить наоборот) Код (Text): const int DayInMonth[2][13]={{31,31,28,31,30,31,30,31,31,30,31,30,31},{31,31,29,31,30,31,30,31,31,30,31,30,31}}; int main(...) { int iDay,iMonth,iYear,iNumberOfMonth,iLeapYear,iDayInOldMonth; printf("Current date(mm/dd/year):"); scanf("%d%*[/]%d%*[/]%d",&iMonth,&iDay,&iYear); printf("Enter how many month to add to current date:"); scanf("%d",&iNumberOfMonth); if(iYear%4) iLeapYear=0;//не высокосный год - при равномерном распределении он будет выподать чаще, а поэтому желательно что бы при этом было как можно меньше сравнений else if(!(iYear%100)) iLeapYear=1;//высокосный год, делится на 4 без остатка, но не делится на 100 else if(iYear%400) iLeapYear=1;//высокосный год, делится на 400 без остатка else iLeapYear=0; //не высокосный год, который делится на 100 iDayInOldMonth=DayInMonth[iLeapYear][iMonth]; if(iNumberOfMonth) iMonth+=(iNumberOfMonth-1); iYear+=iMonth/12; iMonth=iMonth%12+1; if(iYear%4) iLeapYear=0; else if(!(iYear%100)) iLeapYear=1; else if(iYear%400) iLeapYear=1; else iLeapYear=0; iDay=iDay+DayInMonth[iLeapYear][iMonth]-iDayInOldMonth; if(iDay<1) iDay=1; printf("Result date(mm/dd/yyyy):%d/%d/%d",iMonth,iDay,iYear); return 0; } А теперь вопрос, если усложнить задачу, добавив прибавление еще дней и часов(минут, секунд...) то как себя должен вести себя алгоритм в октябре и в марте если добавляемый интервал включает переход с летнего времени на зимнее и обратно? И отражает ли следующий нюанс SystemTimeToFileTime- FileTimeToSystemTime?
Ссори, алгоритм rmn будет все же выдовать ошибку : NewDate:=DateSer(2000,1+1,31) выдаст уже не февраль а март.
CodeTao это не мой алгоритм, я взял его в примерах по delphi. И на счет его работоспособности я тоже сказал, что не проверял. так, в принципе, и должен март выдать. Там же учитывается не только месяц, но и день. Эти 2 (3) дня как раз и добавляют еще один месяц.
rmnЯ не знал как назвать алгоритм, а поэтому слинковал с твоим именем(без обид, если что извини) На счет "так, в принципе, и должен март выдать." как раз нет, представь твою зарплату задержат в критический момент на 3 дня - согласись, не очень приятно.
с ума с вами сойдешь надо сначало определиться, как должно быть, а потом просто написать! например, если нужно, чтобы месяц не перескакивал: Код (Text): void AddMonth(LPSYSTEMTIME IN OUT lpTime, int IN nMonth) { int nMaxDay; lpTime->wMonth+= nMonth; lpTime->wYear+= (lpTime->wMonth-1)/12; lpTime->wMonth= (lpTime->wMonth-1)%12 + 1; switch(lpTime->wMonth) { case 1, 3, 5, 7, 8, 10, 12: nMaxDay= 31; break; case 4, 6, 9, 11: nMaxDay= 30; break; case 2: nMaxDay= (lpTime->wYear%4 || (lpTime->wYear%100 && !(lpTime->wYear%400)))?28:29; break; } if(lpTime->wDay>nMaxDay) lpTime= wDay>nMaxDay; } че то вроде того
Есть еще фунция DataAdd. http://office.microsoft.com/ru-ru/access/HA012288101049.aspx?pid=CH100728911049 DateAdd PROTO pszInterval:PTR BYTE, plNumber:PTR SDWORD, pdt1:PTR FILETIME, pdt2:PTR FILETIME Пример: Код (Text): include \masm32\include\DateTime.inc includelib \masm32\lib\DateTime.lib .data d dw ? delta dd ? ft1 FILETIME<> ft2 FILETIME<> .code fn DateAdd,addr d,addr delta,addr ft1,addr ft2 где: d - символ, чего будем менять. Доступны такие: "s" - секунды, "m" - минуты, "h" - часы, "d" - дни delta - вобщем, сколько хотим добавить или, если отрицательное число, отнять. ft1 - передаем дату в формате FILETIME ft2 - сюда получаем дату в формате FILETIME
http://mc-black.narod.ru/dzp.htm Здесь есть пример календаря. там в одной процедуре рассчитывается разница между двумя датами. немного переделать (вместо вычитания сложение).
ну это уже совсем Код (Text): mov ax, SysTime.dwMonth add ax, 3 mov cl, 12 div cl movzx eax, al все. выводим число из eax. будет на 3 мес больше.