Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.09.2009, 12:38   #21
SuperVisor
Павел Сергеевич
Форумчанин
 
Регистрация: 05.11.2006
Сообщений: 665
По умолчанию

Цитата:
Сообщение от Sasha_Smirnov Посмотреть сообщение
Чушь-то чушь, но она же работает!
Объясню на пальцах...
Переводим дату в дни - отбрасываем знаки после запятой. Вот теперь у Вас есть количество дней с 31 декабря 1889г. Что теперь? У Вас есть конструктивные предложения?! Про такое говорят "Слышу звон, да не знаю где он."
Я же предлагаю за минимум расчетов получить разницу календарей в днях и просто уменьшить/увеличить количество дней в исходной дате, обработав 3(!) исключительных случая на каждые 400 лет.
И я даже знаю, как это работает!

P.S. А за ваш пост вам можно дать нарушение по 2 пунктам:
1.) флуд - т.к. это обычные прерии, не несущие раскрытия темы ни коим образом
2.) нарушение правил форума - т.к. ссылки в данном разделе запрещены. (за это и выдал)
Познавая других, мы познаем себя.
С'est la vie...
SuperVisor вне форума Ответить с цитированием
Старый 23.09.2009, 12:59   #22
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Ну SuperVisor, мне кажется как раз таки Ваш метод весьма мутным, чего уж тут говорить о топикстартере . Насчет дней: тут я считаю все правильным, ему понадобиться 2 функции: перевод с юлианского в дни и с дней в грегорианский.
Как переводить в грегорианский? Да практически также как предлагаете Вы - число дней в году практически фиксировано, нужно будет только делать коррекцию на високосные года по указанным выше правилам.
Такой вариант более универсален, поскольку не содержит исключительных случаев. Единственное ограничение - точкой отсчета будет являться наша эра и дата за ней не будут доступны.
Удобство такого подхода в том, что если ему потом потребуется перевод в календарь мая, то писать нужно будет только одну функцию .
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика

Последний раз редактировалось Utkin; 23.09.2009 в 13:11.
Utkin вне форума Ответить с цитированием
Старый 23.09.2009, 13:16   #23
SuperVisor
Павел Сергеевич
Форумчанин
 
Регистрация: 05.11.2006
Сообщений: 665
По умолчанию

Цитата:
Сообщение от Utkin Посмотреть сообщение
исключительных случаев. Единственное ограничение - точкой отсчета будет являться наша эра и дата за ней не будут доступны.
Под исключительными случаями я подразумеваю лишь отображение даты, когда 29 февраля 1800 года невозможно в типе TDateTime. И его придется вывести самому )
По поводу остального: через пол-часика вложу код с подробными камментами... "Мутный" - есть "не понятный", но не все что не понятно - не верно либо хуже. ))
Познавая других, мы познаем себя.
С'est la vie...
SuperVisor вне форума Ответить с цитированием
Старый 25.09.2009, 01:28   #24
Frame1992
Пользователь
 
Аватар для Frame1992
 
Регистрация: 21.09.2009
Сообщений: 31
По умолчанию

А разницу в днях, на сколько я понимаю можно осуществлять по формуле d=((y/100)-(y/400))-2??

А ведь кто-то хотел даже код написать...

Последний раз редактировалось Stilet; 25.09.2009 в 08:07.
Frame1992 вне форума Ответить с цитированием
Старый 25.09.2009, 08:38   #25
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

ну, я тоже хочу код написать...
почти всё готово, но есть одна мелкая загвоздочка... как только её преодолею, считайте готовый код уже в кармане!
загвоздка вот в чём.
я набросал функцию (не сам, воспользовался чужими наработками, в частности, кодом (c) T. R. Willmitch)
которая определяет разность в днях между Юлианской и Григорианскими датами.
вот эта функция:
Код:
FUNCTION DiffJulDay (Day, Month, Year  : INTEGER) : integer;
VAR       A : LONGINT;
     Gregorian : BOOLEAN;

BEGIN
  Gregorian := TRUE;

(* Check if the date is Gregorian, beginning 1582 October 15.               *)

  IF Year < 1582 THEN Gregorian := FALSE;
  IF (Year = 1582) AND (Month < 10) THEN Gregorian := FALSE;
  IF (Year = 1582) AND (Month = 10) THEN
    IF Day < 15 THEN Gregorian := FALSE;

  IF Month < 3 THEN BEGIN
    Year := Year - 1;
    Month := Month + 12
  END;  (* IF *)

  A := Year DIV 100;

  IF Gregorian THEN
    DiffJulDay := 2 - A + A DIV 4
  ELSE
    DiffJulDay := 0;

END;  (* FUNCTION DiffJulDay *)
но, проблема в том, что на входе в эту функцию должны быть месяц, день и год в Григорианском формате. тогда она возвращает корректное значение разницы в днях... а в данном случае нужно наоборот, по Юлианской дате получить эту самую разницу... ошибка будет возникать вблизи критичных дат (конец февраля 1700, 1800 и 1900 годов)
Serge_Bliznykov вне форума Ответить с цитированием
Старый 25.09.2009, 11:54   #26
SuperVisor
Павел Сергеевич
Форумчанин
 
Регистрация: 05.11.2006
Сообщений: 665
По умолчанию

Извиняюсь за задержку. Работа, дом... Откровенно - на код потратил часа 2. От Datetime отказался. Если нужны будут 5 тысяч с лишним лет, добавите сами...
This is universal CODE:
Код:
function DateTimeCalendarConvert(var DD, MM, YYYY: integer; OurAge: Boolean; ToJuly: Boolean): String;
  var
    DInc: integer;
    Vs: Boolean;

  //Процедура создана для того, чтобы узнать, високосный ли год по тому или иному календарю
    procedure GetVS;
    begin
      if ToJuly then         //Если переводим в Юлианский - то узнаем високосен ли год в той системе
        Vs:=((YYYY mod 4) = 0)
      else                   //Иначе узнаем високосность Григорианского календаря
        Vs:=(((YYYY mod 4) = 0) and not ((YYYY mod 100) = 0)) or ((YYYY mod 400) = 0);
    end;
  begin
  // Узнаем количество веков от начала эры
    DInc:=trunc(YYYY/100);
  //Если до нашей эры и год - не начало эры вычитаем 1 из разницы.
    if not OurAge and (DInc<>0) then Dec(DInc);
  //Почему, спросите вы??? Да потому что нулевого года нет, а начало эры есть. От
  // 100 года до нашей эры до 100 года нашей эры - 2 века, про это забывать нельзя.

  //Узнаем разницу между календарями в днях. Берем условную точку - начало эры.
    DInc:=(DInc div 4)*3 + (DInc mod 4);

  //                      ИСКЛЮЧЕНИЕ ПЕРВОЕ
  //Учитывая условность предыдущего действия и зная, что календари сошлись в 200 году
  //в зависимости от эры прибавляем или отнимаем 2 дня, которые по расчету прибавились
  //за 100й год и 200й год
    if OurAge then
      dec(DInc,2)
    else

    begin
      inc(DInc,2);
      DInc:=-DInc;
    end;

  //                      ИСКЛЮЧЕНИЕ ВТОРОЕ
  //Если год високосен в Юлианском, но не високосен в Григореанском календаре и
  //нам нужен перевод в Григореанский календарь
    if (YYYY mod 100=0) and not (YYYY mod 400=0) and not ToJuly then
  //а 1 марта еще не наступило
        if (MM<2) or ((MM=2) and (DD<=29)) then
  //значит разница в 1 день за этот год еще не действует.
          if OurAge then dec(DInc) else inc(DInc);

  //Прибавляем/вычитаем дни
    if ToJuly then
      DD:=DD-DInc
    else
      DD:=DD+DInc;
  //Получаем високосность текущего года в нужной системе
    GetVs;

  //Если количество дней больше, чем положено в данном месяце текущего года
    while DD > MonthDays[Vs][MM] do
    begin
    //Вычитаем дни, прибавляем месяц
      DD:=DD-MonthDays[Vs][MM];
      Inc(MM);
    //Проверяем, не кончился ли год при переводе
      if MM>12 then
      begin
        Inc(YYYY);
        MM:=1;
        GetVs;
      end;
    end;

  //То же самое, только в другую сторону
    while DD <= 0 do
    begin

      if MM=1 then
      begin
        MM:=12;
        Dec(YYYY);
        GetVS;
      end

      else Dec(MM);

      DD:=MonthDays[Vs][MM]+DD;
    end;
  //Генерим результат
    Result:=inttostr(DD)+' '+LongMonthNames[MM]+' '+inttostr(YYYY)+'г.';
  //Добавляем постфикс, если необходимо
    if Not OurAge then Result:=Result+' до н.э.';
  end;
P.S. Решение на Delphi - на чем умею, на том и пишу... Пусть C++ гуру помогут в переносе.
Познавая других, мы познаем себя.
С'est la vie...

Последний раз редактировалось SuperVisor; 25.09.2009 в 13:07.
SuperVisor вне форума Ответить с цитированием
Старый 25.09.2009, 12:57   #27
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

SuperVisor, проверил Ваше решение (практически во всём диапозе вообразимых дат от 1 г.н.э. до 10000 г.н.э.)
Всё работает!
Serge_Bliznykov вне форума Ответить с цитированием
Старый 25.09.2009, 13:31   #28
SuperVisor
Павел Сергеевич
Форумчанин
 
Регистрация: 05.11.2006
Сообщений: 665
По умолчанию

Serge_Bliznykov, оно еще и в оба направления работает и с разными эрами.. )

Для удобоваримости перевода еще некоторые нюансы Вам в помощь:
Код:
type
  TDayTable = array[1..12] of Word;
const
  MonthDays: array [Boolean] of TDayTable =
    ((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
     (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));
  LongMonthNames: array[1..12] of string = 
    ('Января', 'Февраля', 'Марта', 'Апреля', 'Мая', 'Июня', 'Июля', 'Августа', 'Сентября',
     'Октября', 'Ноября', 'Декабря');
P.S. По Юлианскому календарю сейчас 7517 год, т.е. разница между ними в 5508 лет.
Познавая других, мы познаем себя.
С'est la vie...
SuperVisor вне форума Ответить с цитированием
Старый 25.09.2009, 13:50   #29
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
LongMonthNames: array[1..12] of string =
('Января', 'Февраля', 'Марта', 'Апреля', 'Мая', 'Июня', 'Июля', 'Августа', 'Сентября',
'Октября', 'Ноября', 'Декабря');
Ну это можно заменить:
Код:
formatDateTime('mmmm',Дата);
Причем что мне в этом нравится, так независимость от языка. Буит стоять греческий - по гречески будет писать названия месяцев. Рекомендую
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 25.09.2009, 14:01   #30
SuperVisor
Павел Сергеевич
Форумчанин
 
Регистрация: 05.11.2006
Сообщений: 665
По умолчанию

Виталий, тут просто на C++ надо, а какие в нем возможности я, к сожалению, не знаю.. Потому так.
В Delphi LongMonthNames[] берется из системных параметров.. Ну я на всякий случай и описал.. )))
Познавая других, мы познаем себя.
С'est la vie...
SuperVisor вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Задачка по С++ Ready Помощь студентам 2 20.05.2009 01:19
задачка lucky Помощь студентам 1 07.05.2009 13:49
Задачка на С!!! Exorcist Помощь студентам 1 07.12.2008 21:15
Задачка Claster Помощь студентам 2 24.09.2008 17:53