Ещё одна версия для вычисления номера юлианской даты. В этой версии можно вычислять разность дат. Например Код (Text): JD 24.02.2022 7.10.2023 Должно получится 590, это время прошедших полных суток. Аверы? Агрятся только четыре, думают что там троян, очень тупые аверы!!! Непосредственно код. Код (ASM): ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Julian Day Number v0.04 ;; (c) NanoBot ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .386 .model flat, stdcall option casemap:none include msvcrt.inc include macros.asm SDate struct day dword ? ;1..31 mon dword ? ;1..12 year dword ? SDate ends .const LengthMON sdword 31,28,31,30,31,30,31,31,30,31,30,31 .code int_div MACRO a:req, b:req IFDIFI <a>, <eax> mov eax, a ENDIF mov ecx, b cdq idiv ecx ENDM int_div$ MACRO a:req, b:req int_div a, b EXITM <eax> ENDM align_proc GetJDN proc (dword) uses esi edi ebx date:ptr SDate mov edx, date ASSUME edx:ptr SDate mov esi, [edx].day ;JDN mov ebx, [edx].mon ;mon //1..12 mov edi, [edx].year ;year ASSUME edx:nothing ;/* Новый год 1 марта! */ sub ebx, 2+1 sbb eax, eax ;k = mon=-2+1<0 ? -1 : 0; ;year += 4800+k; lea edi, [edi+eax+4800] ;mon += k & 12; and eax, 12 add ebx, eax ;JDN += mon*30+(mon%5+1)/2+mon/5*3; imul eax, ebx, 30 add esi, eax int_div ebx, 5 lea eax, [eax*2+eax] ;*=3 add esi, eax lea eax, [edx+1] cdq sub eax, edx sar eax, 1;/=2 add esi, eax ;JDN += year*365+year/4+year/400-year/100-32045; imul eax, edi, 365 add esi, eax add esi, int_div$(edi, 4) add esi, int_div$(edi, 400) sub esi, int_div$(edi, 100) lea eax, [esi-32045] ret GetJDN endp ;GetMJD("17.11.1858") align_proc GetDDpMMpYYYY proc (byte) uses esi edi ebx strDate:ptr byte, date:ptr SDate local strEnd:ptr byte, leap:sdword ;day:esi, mon:edi, year:ebx ASSUME ecx:ptr byte, edx:ptr SDate mov esi, strtol(strDate, &strEnd, 10) mov ecx, strEnd .if ([ecx]=='.') inc ecx mov edi, strtol(ecx, &strEnd, 10) mov ecx, strEnd .if ([ecx]=='.') inc ecx mov ebx, strtol(ecx, &strEnd, 10) mov ecx, strEnd .if ([ecx]==0) dec edi .if (edi<12) and leap, 0 .if (edi==2-1) int_div ebx, 4 .if (edx==0) int_div ebx, 400 .if (edx!=0) inc leap .endif .endif .endif mov ecx, LengthMON[edi*4] add ecx, leap .if (sdword ptr esi>=1 && sdword ptr esi<=ecx) mov edx, date inc edi mov [edx].day, esi mov [edx].mon, edi mov [edx].year, ebx mov al, true jmp EXIT .endif .endif .endif .endif .endif ASSUME ecx:nothing, edx:nothing printf("Date format error: '%s'\n", strDate) ;Ошибка формата даты mov al, false EXIT: ret GetDDpMMpYYYY endp align_proc main proc C argc:sdword, argv:ptr ptr, envp:ptr ptr local date1:SDate, date2:SDate .repeat .if (argc<2) printf("Usage: JD DD.MM.YYYY [DD.MM.YYYY]\n") .else mov esi, argv .if (argc==2) .break .if (GetDDpMMpYYYY([esi+1*4], &date1)==false) GetJDN(&date1) printf("%d.%02d.%d, JD = %ld\n", date1.day, date1.mon, date1.year, eax) .else .break .if (GetDDpMMpYYYY([esi+2*4], &date2)==false) mov ebx, GetJDN(&date2) .break .if (GetDDpMMpYYYY([esi+1*4], &date1)==false) sub ebx, GetJDN(&date1) printf("%d.%02d.%d - %d.%02d.%d = %ld\n", date1.day, date1.mon, date1.year, date2.day, date2.mon, date2.year, ebx) .endif .endif .until true xor eax, eax ret main endp main_startup3_END ЗЫ 5 аверов агрятся!!! Версия на С/С++. Код (C++): //////////////////////////////////////////////////////////////////// // Julian Day Number v0.051 // (c) NanoBot //////////////////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> struct SDate { int day; //1..31 int mon; //1..12 int year; }; const int LengthMON[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; long GetJDN(SDate *date) { long JDN = date->day; int mon = date->mon-1; //1..12 int year = date->year; mon-=2; /* Новый год 1 марта! */ int k = mon<0 ? -1 : 0; year += 4800+k; mon += k & 12; JDN += mon*30+(mon%5+1)/2+mon/5*3; JDN += year*365+year/4+year/400-year/100-32045; return JDN; } void GetDate(long JDN, SDate *date) { int j400,j100,j4,j1,year,mon; int m5,m2,m1; const int days400year = 400*365+97; const int days100year = 100*365+24; const int days4year = 4*365+1; const int days1year = 1*365; const int days5mon = 5*30+3; const int days2mon = 2*30+1; const int days1mon = 1*30+1; long day = JDN+32045-1; j400 = day/days400year; day %= days400year; j100 = day/days100year; day %= days100year; j4 = day/days4year; day %= days4year; j1 = day/days1year; day %= days1year; if (j1==4){//високосный день j1--; day = 365; } year = j400*400+j100*100+j4*4+j1-4800; m5 = day/days5mon; day %= days5mon; m2 = day/days2mon; day %= days2mon; m1 = day/days1mon; day %= days1mon; mon = m5*5+m2*2+m1+3; if (mon > 12){ mon -= 12; year++; } date->day = day + 1; date->mon = mon; date->year = year; } bool GetDDpMMpYYYY(const char *strDate, SDate *date) { char *strEnd; int day = strtol(strDate, &strEnd, 10); if (strEnd[0]=='.'){ int mon = strtol(strEnd+1, &strEnd, 10); if (strEnd[0]=='.'){ int year = strtol(strEnd+1, &strEnd, 10); if (strEnd[0]==0){ if (mon>=1 && mon<=12){ int lenMon = LengthMON[mon-1]; if (mon==2 && year%4==0 && year%100!=0 || year%400==0) lenMon++; if (day>=1 && day<=lenMon){ date->day = day; date->mon = mon; date->year = year; return true; } } } } } printf("Date format error: '%s'\n", strDate); //Ошибка формата даты return false; } int main(int argc, const char *argv[]) { SDate date1, date2; char *strEnd; if (argc<2) printf("Usage: JD DD.MM.YYYY [DD.MM.YYYY]\n"); else { long JDN; if (argc==2){ JDN = strtol(argv[1], &strEnd, 10); if (strEnd[0]==0){ GetDate(JDN, &date1); printf("%ld = %d.%02d.%d\n", JDN, date1.day, date1.mon, date1.year); } else { if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN = GetJDN(&date1); printf("%d.%02d.%d = %ld\n", date1.day, date1.mon, date1.year, JDN); } } else { JDN = strtol(argv[2], &strEnd, 10); if (strEnd[0]==0){ if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN += GetJDN(&date1); GetDate(JDN, &date2); printf("%d.%02d.%d + %s = %d.%02d.%d\n", date1.day, date1.mon, date1.year, argv[2], date2.day, date2.mon, date2.year); } else { if (GetDDpMMpYYYY(argv[2], &date2)==false) return 0; JDN = GetJDN(&date2); if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN = JDN - GetJDN(&date1); printf("%d.%02d.%d - %d.%02d.%d = %ld\n", date1.day, date1.mon, date1.year, date2.day, date2.mon, date2.year, JDN); } } } return 0; }
Исправил ошибку определения високосного года в GetDDpMMpYYYY Добавил возможность номер дня переводить в дату. Из даты вычитать/прибавлять количество дней. В общем, новые возможности можно посмотреть в батнике тест. И программа на С/С++, на чистом С должна откомпилироваться, на новых редакциях точно. Код (C++): //////////////////////////////////////////////////////////////////// // Julian Day Number v0.05 // (c) NanoBot //////////////////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> struct SData { int day; //1..31 int mon; //1..12 int year; }; const int LengthMON[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; int GetJDN(SData *date) { int JDN = date->day; int mon = date->mon-1; //1..12 int year = date->year; mon-=2; /* Новый год 1 марта! */ int k = mon<0 ? -1 : 0; year += 4800+k; mon += k & 12; JDN += mon*30+(mon%5+1)/2+mon/5*3; JDN += year*365+year/4+year/400-year/100-32045; return JDN; } void GetData(int JDN, SData *data) { int j400,j100,j4,j1,year,mon,day; int m5,m2,m1; const int days400year = 400*365+97; const int days100year = 100*365+24; const int days4year = 4*365+1; const int days1year = 1*365; const int days5mon = 5*30+3; const int days2mon = 2*30+1; const int days1mon = 1*30+1; day = JDN+32045-1; j400 = day/days400year; day %= days400year; j100 = day/days100year; day %= days100year; j4 = day/days4year; day %= days4year; j1 = day/days1year; day %= days1year; if (j1==4){//високосный день j1--; day = 365; } year = j400*400+j100*100+j4*4+j1-4800; m5 = day/days5mon; day %= days5mon; m2 = day/days2mon; day %= days2mon; m1 = day/days1mon; day %= days1mon; mon = m5*5+m2*2+m1+3; if (mon > 12){ mon -= 12; year++; } data->day = day + 1; data->mon = mon; data->year = year; } bool GetDDpMMpYYYY(const char *strDate, SData *date) { char *strEnd; int day = strtol(strDate, &strEnd, 10); if (strEnd[0]=='.'){ int mon = strtol(strEnd+1, &strEnd, 10); if (strEnd[0]=='.'){ int year = strtol(strEnd+1, &strEnd, 10); if (strEnd[0]==0){ if (mon>=1 && mon<=12){ int lenMon = LengthMON[mon-1]; if (mon==2 && year%4==0 && year%100!=0 || year%400==0) lenMon++; if (day>=1 && day<=lenMon){ date->day = day; date->mon = mon; date->year = year; return true; } } } } } printf("Date format error: '%s'\n", strDate); //Ошибка формата даты return false; } int main(int argc, const char *argv[]) { SData date1, date2; char *strEnd; if (argc<2) printf("Usage: JD DD.MM.YYYY [DD.MM.YYYY]\n"); else { int JDN; if (argc==2){ JDN = strtol(argv[1], &strEnd, 10); if (strEnd[0]==0){ GetData(JDN, &date1); printf("%ld = %d.%02d.%d\n", JDN, date1.day, date1.mon, date1.year); } else { if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN = GetJDN(&date1); printf("%d.%02d.%d = %ld\n", date1.day, date1.mon, date1.year, JDN); } } else { JDN = strtol(argv[2], &strEnd, 10); if (strEnd[0]==0){ if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN += GetJDN(&date1); GetData(JDN, &date2); printf("%d.%02d.%d + %s = %d.%02d.%d\n", date1.day, date1.mon, date1.year, argv[2], date2.day, date2.mon, date2.year); } else { if (GetDDpMMpYYYY(argv[2], &date2)==false) return 0; JDN = GetJDN(&date2); if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN = JDN - GetJDN(&date1); printf("%d.%02d.%d - %d.%02d.%d = %ld\n", date1.day, date1.mon, date1.year, date2.day, date2.mon, date2.year, JDN); } } } return 0; }
Некоторые типы не совсем правильно определил, для локальных JDN и day в GetData надо long. Иначе если у вас всё ещё АТ/286 и турбоСи 3, программка может и не работать. В прочим, сейчас int сто пудово 32-битный тип. --- Сообщение объединено, 15 окт 2023 --- Код (C++): //////////////////////////////////////////////////////////////////// // Julian Day Number v0.051 // (c) NanoBot //////////////////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> struct SData { int day; //1..31 int mon; //1..12 int year; }; const int LengthMON[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; long GetJDN(SData *data) { long JDN = data->day; int mon = data->mon-1; //1..12 int year = data->year; mon-=2; /* Новый год 1 марта! */ int k = mon<0 ? -1 : 0; year += 4800+k; mon += k & 12; JDN += mon*30+(mon%5+1)/2+mon/5*3; JDN += year*365+year/4+year/400-year/100-32045; return JDN; } void GetData(long JDN, SData *data) { int j400,j100,j4,j1,year,mon; int m5,m2,m1; const int days400year = 400*365+97; const int days100year = 100*365+24; const int days4year = 4*365+1; const int days1year = 1*365; const int days5mon = 5*30+3; const int days2mon = 2*30+1; const int days1mon = 1*30+1; long day = JDN+32045-1; j400 = day/days400year; day %= days400year; j100 = day/days100year; day %= days100year; j4 = day/days4year; day %= days4year; j1 = day/days1year; day %= days1year; if (j1==4){//високосный день j1--; day = 365; } year = j400*400+j100*100+j4*4+j1-4800; m5 = day/days5mon; day %= days5mon; m2 = day/days2mon; day %= days2mon; m1 = day/days1mon; day %= days1mon; mon = m5*5+m2*2+m1+3; if (mon > 12){ mon -= 12; year++; } data->day = day + 1; data->mon = mon; data->year = year; } bool GetDDpMMpYYYY(const char *strDate, SData *data) { char *strEnd; int day = strtol(strDate, &strEnd, 10); if (strEnd[0]=='.'){ int mon = strtol(strEnd+1, &strEnd, 10); if (strEnd[0]=='.'){ int year = strtol(strEnd+1, &strEnd, 10); if (strEnd[0]==0){ if (mon>=1 && mon<=12){ int lenMon = LengthMON[mon-1]; if (mon==2 && year%4==0 && year%100!=0 || year%400==0) lenMon++; if (day>=1 && day<=lenMon){ data->day = day; data->mon = mon; data->year = year; return true; } } } } } printf("Date format error: '%s'\n", strDate); //Ошибка формата даты return false; } int main(int argc, const char *argv[]) { SData date1, date2; char *strEnd; if (argc<2) printf("Usage: JD DD.MM.YYYY [DD.MM.YYYY]\n"); else { long JDN; if (argc==2){ JDN = strtol(argv[1], &strEnd, 10); if (strEnd[0]==0){ GetData(JDN, &date1); printf("%ld = %d.%02d.%d\n", JDN, date1.day, date1.mon, date1.year); } else { if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN = GetJDN(&date1); printf("%d.%02d.%d = %ld\n", date1.day, date1.mon, date1.year, JDN); } } else { JDN = strtol(argv[2], &strEnd, 10); if (strEnd[0]==0){ if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN += GetJDN(&date1); GetData(JDN, &date2); printf("%d.%02d.%d + %s = %d.%02d.%d\n", date1.day, date1.mon, date1.year, argv[2], date2.day, date2.mon, date2.year); } else { if (GetDDpMMpYYYY(argv[2], &date2)==false) return 0; JDN = GetJDN(&date2); if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN = JDN - GetJDN(&date1); printf("%d.%02d.%d - %d.%02d.%d = %ld\n", date1.day, date1.mon, date1.year, date2.day, date2.mon, date2.year, JDN); } } } return 0; } Исправил, теперь код будет работать на самых древних машинах. Возможно будет термояд. война, будешь рад и 16 битной пекашки если выживешь!
чет в отрицательную вселенную ваша прога иногда заскакивает не страшно в вечной мерзлоте? Код (Text): 15.10.2023 + 99999999999999999999 = -25.-7.-5877586
alex_dz, допустимый диапазон +- 5879489 год, потом происходит переполнение. А так предполагается что пользователь вводит вменяемые параметры, хотя бы в пределах 10'000 лет.
никогда не доверяй юзеру (с) MCMXIILVK --- Сообщение объединено, 15 окт 2023 --- из-за таких вот предполагается потом уйма CVE зеродеев и подрывов атомных станций в Иране и Фукусиме
alex_dz, я там немного накосячил с типами, в общем алгоритм предполагает положительные типа данные, точней беззнаковые типа кроме year. Возможно точку ноль надо не 4800 год до нашей эры, а MIN_INT. Тогда отрицательных чисел не будет. В общем, функция GetDate правильно работает до 2147451603, а потом выдаёт ошибку. --- Сообщение объединено, 16 окт 2023 --- Код (C++): //////////////////////////////////////////////////////////////////// // Julian Day Number v0.06 // (c) NanoBot //////////////////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> struct SDate { int day; //1..31 int mon; //1..12 int year; }; const int LengthMON[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; const int days400year = 400*365+97; const int days100year = 100*365+24; const int days4year = 4*365+1; const int days1year = 1*365; const int days5mon = 5*30+3; const int days2mon = 2*30+1; const int days1mon = 1*30+1; long GetJDN(SDate *date) { unsigned long JDN = date->day; int mon = date->mon-1; //1..12 unsigned long year = date->year; mon-=2; /* Новый год 1 марта! */ int k = mon<0 ? -1 : 0; year += 4800+k + 5879600; mon += k & 12; JDN += mon*30+(mon%5+1)/2+mon/5*3; JDN += year*365+year/4+year/400-year/100-32045; return JDN - 2147479803; } void GetDate(long JDN, SDate *date) { unsigned int j400,j100,j4,j1,year; unsigned int mon,m5,m2,m1; unsigned long day = JDN+32045-1+2147479803; j400 = day/days400year; day %= days400year; j100 = day/days100year; day %= days100year; j4 = day/days4year; day %= days4year; j1 = day/days1year; day %= days1year; if (j1==4){//високосный день j1--; day = 365; } year = j400*400+j100*100+j4*4+j1-4800 - 5879600; m5 = day/days5mon; day %= days5mon; m2 = day/days2mon; day %= days2mon; m1 = day/days1mon; day %= days1mon; mon = m5*5+m2*2+m1+3; if (mon > 12){ mon -= 12; year++; } date->day = day + 1; date->mon = mon; date->year = year; } bool GetDDpMMpYYYY(const char *strDate, SDate *date) { char *strEnd; int day = strtol(strDate, &strEnd, 10); if (strEnd[0]=='.'){ int mon = strtol(strEnd+1, &strEnd, 10); if (strEnd[0]=='.'){ int year = strtol(strEnd+1, &strEnd, 10); if (strEnd[0]==0){ if (mon>=1 && mon<=12){ int lenMon = LengthMON[mon-1]; if (mon==2 && year%4==0 && year%100!=0 || year%400==0) lenMon++; if (day>=1 && day<=lenMon){ date->day = day; date->mon = mon; date->year = year; return true; } } } } } printf("Date format error: '%s'\n", strDate); //Ошибка формата даты return false; } int main(int argc, const char *argv[]) { SDate date1, date2; char *strEnd; if (argc<2) printf("Usage: JD DD.MM.YYYY [DD.MM.YYYY]\n"); else { long JDN; if (argc==2){ JDN = strtol(argv[1], &strEnd, 10); if (strEnd[0]==0){ GetDate(JDN, &date1); printf("%ld = %d.%02d.%d\n", JDN, date1.day, date1.mon, date1.year); } else { if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN = GetJDN(&date1); printf("%d.%02d.%d = %ld\n", date1.day, date1.mon, date1.year, JDN); } } else { JDN = strtol(argv[2], &strEnd, 10); if (strEnd[0]==0){ if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN += GetJDN(&date1); GetDate(JDN, &date2); printf("%d.%02d.%d + %s = %d.%02d.%d\n", date1.day, date1.mon, date1.year, argv[2], date2.day, date2.mon, date2.year); } else { if (GetDDpMMpYYYY(argv[2], &date2)==false) return 0; JDN = GetJDN(&date2); if (GetDDpMMpYYYY(argv[1], &date1)==false) return 0; JDN = JDN - GetJDN(&date1); printf("%d.%02d.%d - %d.%02d.%d = %ld\n", date1.day, date1.mon, date1.year, date2.day, date2.mon, date2.year, JDN); } } } return 0; } Ну тут исправил, как я сказал проблемы с отрицательными числами, а алгоритм ожидает положительные числа. Хотя возможно есть какой-то не допустимый диапазон, где результат не правильный. Но по жизни и старый код работал, нехрен забивать заведомо бредовые параметры. Минус 10 тыс лет или даже 100 тыс, плюс 10 тыс лет вам хватит. А в пределах несколько столетий туда сюда, точно всё работает.