Астрономический календарь
От: Mira  
Дата: 11.02.06 23:40
Оценка:
Привет всем!

Возникла сл. проблемма... Пишу исходник астрономического календаря.
От обычного календаря он отличается лишь тем, что в нем присутствует нулевой год.
Новая эра, как обычно, начинается с 1 января 1 года.

Существует взаимно однозначное соответствие между датой и целочисленным значением:

N = Y.M.D
...
-10 = 0.12.21
-9 = 0.12.22
-8 = 0.12.23
-7 = 0.12.24
-6 = 0.12.25
-5 = 0.12.26
-4 = 0.12.27
-3 = 0.12.28
-2 = 0.12.29
-1 = 0.12.30
0 = 0.12.31
1 = 1.1.1
2 = 1.1.2
3 = 1.1.3
4 = 1.1.4
5 = 1.1.5
6 = 1.1.6
7 = 1.1.7
8 = 1.1.8
9 = 1.1.9
10 = 1.1.10
...

Получить N из Y, M, D довольно легко...
Однако затруднительно написать компактный алгоритм преобразования целочисленного
значения в соответствующую дату. Может кто-нибудь поможет?
Нужно получить Y, M, D обратно из N.

-------------------------

Напомню: Существуют обычные и высокосные года. В высокосных годах в феврале 29 дней,
а в обычных 28. Год считается высокосным если его значение кратно 4, тем не менее
года кратные 100 не считаются высокосными, а года кратные 400 считаются.
Например:

-8, -4, 0, 4, 8, 400, 800, 2000 — высокосные года
-3, -2, -1, 1, 2, 3, 100, 200 — не высокосные года

Вот функция реализующая это:

bool IsLeapYear(short Y) { return !(Y % 4) && ((Y % 100) || !(Y % 400)); }

-------------------------

Алгоритм прямого преобразования:

#define MAXDATE 3652059L
#define MINDATE -3652059L

typedef const short DateTable[2][12];

DateTable MonthDays = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };

DateTable PastMonthDays = {
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } };

bool EncodeDate(short Y, short M, short D, long * RawDate)
{
bool YearType = IsLeapYear(Y);
M--; D--;
if ((unsigned short) M < 12 && (unsigned short) D <= MonthDays[YearType][M])
{
long iRawDate = D + PastMonthDays[YearType][M] + (Y — 1) * 365;
if (Y > 0) {iRawDate++; Y--;}
iRawDate += Y / 4 — Y / 100 + Y / 400;
if (iRawDate >= MINDATE && iRawDate <= MAXDATE)
{
*RawDate = iRawDate;
return true;
}
}
return false;
}

-------------------------

Алгоритм обратного преобразования:

bool DecodeDate(long RawDate, short * Y, short * M, short * D)
{
if (RawDate >= MINDATE && RawDate <= MAXDATE)
{

// ????????????

return true;
}
return false;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.