Kamil Izdebski

Kamil Izdebski Administrator sieci

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Usunąłem, ze względu na głupoty jakie tu występowały :).Kamil Izdebski edytował(a) ten post dnia 21.12.09 o godzinie 16:49
Szymon Kubisiak

Szymon Kubisiak Developer aplikacji
mobilnych Android

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Udało Ci się stworzyć kod nieodczytywalny!
Gratz!
Kamil Izdebski

Kamil Izdebski Administrator sieci

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Już znalazłem błędy, dzięki faktycznie namieszałem ;)))
Szymon Kubisiak

Szymon Kubisiak Developer aplikacji
mobilnych Android

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Nie masz za co dziękować - ale cieszę się że się udało :)
Może podziel to na funkcje zanim pokażesz do oceny...Szymon Kubisiak edytował(a) ten post dnia 21.12.09 o godzinie 16:52
Adam Woźniak

Adam Woźniak software architect
and developer

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Kamil Izdebski:
przesuwanie dat o zadaną liczbę dni

Jeśli to jest zadanie na zaliczenie to rozumiem, że dlatego implementujesz to ręcznie.

Jeśli nie jest to na zaliczenie, to osobiście pomyślałbym nad wsparciem się jakimiś dostępnymi bibliotekami (zamiast pisać ręcznie).

Pozdrawiam, Adam
Kamil Izdebski

Kamil Izdebski Administrator sieci

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Szymon Kubisiak:
Nie masz za co dziękować - ale cieszę się że się udało :)
Może podziel to na funkcje zanim pokażesz do oceny
Tak podzielę, starałem się kod przedstawić w najprostszej postaci.
Adam Woźniak:
Jeśli to jest zadanie na zaliczenie to rozumiem, że dlatego implementujesz to ręcznie.

Jeśli nie jest to na zaliczenie, to osobiście pomyślałbym nad wsparciem się jakimiś dostępnymi bibliotekami (zamiast pisać ręcznie).
Jest tylko częścią zaliczenia i z wykorzystaniem funkcji gotowych. Ja jednak swoje chcę napisać.

Siedzę i piszę, coraz trudniej mi się myśli. W razie problemów zgłoszę się z prośbą o pomoc.

PS. Właśnie opisywałem swój kolejny problem, lecz opisując go znalazłem rozwiązanie:).
Adam Woźniak

Adam Woźniak software architect
and developer

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Kamil Izdebski:
Adam Woźniak:
Jeśli to jest zadanie na zaliczenie to rozumiem, że dlatego implementujesz to ręcznie.
>
Jest tylko częścią zaliczenia i z wykorzystaniem funkcji gotowych. Ja jednak swoje chcę napisać.

Ręczne operacje na datach to żmudna i niewdzięczna robota.

Np. trzeba jakoś uwzględnić lata przestępne:
http://pl.wikipedia.org/wiki/Rok_przest%C4%99pny#Algorytm

Pozdro, Adam
Kamil Izdebski

Kamil Izdebski Administrator sieci

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Tzn, mam daną jakaś datę w postaci DD-MM-YYYY i już napisałem funkcję, która konwertuje mi ją do unix time - czyli liczby sekund od 1.1.1970r. Teraz chcę przesunąć ją o X dni. Więc dodaję do unix time X*86400 sekund. Po czym trzeba ją konwertować w drugą stronę do "zapisu ludzkiego", czyli DD-MM-YYY.

I tutaj zaczęły się schody, przede wszystkim nie wiem dlaczego jeśli mam przykładowo datę 22-3-1973 to po dodaniu liczby wskazującej na 30 lub 31 tego samego miesiąca on mi wypluwa 0 lub 1 następnego miesiąca. Skąd tam to 0 to nie wiem jeszcze.

Postaram się opisać działanie na zasadzie co jak wykonuję (kod też mogę pokazać).

Przykładowo mam taką tablicę tabRoznicyLat = {0,0,1} co by oznaczało, że 0 to rok zwykły, a 1 przestępny.

sekundy - przechowuje ilość sekund od 1.1.1970r (unix epoch)
rok_zwykly - liczba sekund dla roku nieprzestępnego
rok_przestepny - liczba sekund dla roku przestępnego

/* zlicza lata */
int liczLat=0, i=0;
while (sekundy>rok_zwykly || sekundy>rok_przestepny)
{
if (tabRoznicyLat[i]==0)
{
liczLat++;
sekundy-=rok_zwykly;
}
if (tabRoznicyLat[i]==1)
{
liczLat++;
sekundy-=rok_przestepny;
}
i++;
}

Wyjdzie nam liczba lat, które mineły od początku unix epoch więc trzeba dodać do wyniku 1970, czyli liczLat+1970.

Wciąż bazujemy na tej samej zmiennej sekundy (pomniejszonej).
Tablice dla roku zwykłego i przestępnego:
tMiesZ[12] = {l31,l28,l31,l30,l31,l30,l31,l31,l30,l31,l30,l31};
tMiesP[12] = {l31,l29,l31,l30,l31,l30,l31,l31,l30,l31,l30,l31};
Przykładowo l31 to liczba sekund dla miesiąca, który ma 31 dni.


/* zlicza miesiace */
int liczMiesiecy=0, licznik=0;

while(licznik<roznicaLat)
{
for (int i=0; i<12; i++)
{
if (tabRoznicyLat[licznik]==1) //to przestepny
{
if (sekundy>tMiesP[i])
{
liczMiesiecy++;
sekundy-=tMiesP[i];
}
}
else //nieprzestepny
{
if (sekundy>tMiesZ[i])
{
liczMiesiecy++;
sekundy-=tMiesZ[i];
}
}
}
licznik++;
}

No i do wyniku liczby miesięcy musimy dodać 1 bo funkcja ostatniego miesiąca nie uzna nam za pełny, który może się składać przykładowo z 10 dni.

l1 to 86400 sekund, czyli jeden dzień

/* zlicza dni */
int liczDni=0;
while (sekundy>=l1)
{
liczDni++;
sekundy-=l1;
}


I nie wiem dlaczego, ale nie działa mi to jak należy. Przykładowo jeśli mam datę 22-3-1973 w sekundach oczywiście i do niej dodaję dni to (marzec ma 31 dni):

1-6 //dodaje prawidłowo
7 //wyświetla mi datę 1.4.1973
8 //wyświetla mi datę 2.4.1973
9 //wyświetla mi datę 1.4.1973
10 //wyświetla mi datę 1.4.1973 odtąd już dobrze...

Nie mam pojęcia skąd takie wyniki.. a gdy rok zmienię na przestępny to jeszcze dzień 0 mi się pokazuje...Kamil Izdebski edytował(a) ten post dnia 21.12.09 o godzinie 19:24
Łukasz C.

Łukasz C. Senior Technical
Architect

Temat: [C++] przesuwanie dat o zadaną liczbę dni

e...?

nie wiem czemu ale mam poczucie ze z tym bedzie latwiej i przyjemniej: http://pl.wikipedia.org/wiki/Data_Julia%C5%84ska
Kamil Izdebski

Kamil Izdebski Administrator sieci

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Nawet ciekawe, tylko co ma oznaczać, przykładowo Y = INT ((X + 32044,5) / 36524,25) = 67

drugi znak przypisania? to komentarz? :-/


R – Rok
M – Miesiąc
D – Dzień
JD – Dni Juliańskie

W = JD + 0.5 = 2441925
X = INT (W) = 2441925
U = W – X = 0
Y = INT ((X + 32044,5) / 36524,25) = 67
Z = X + Y – INT (Y / 4) – 38 = 2441938
A = Z + 1524 = 2443462
B = INT ((A – 122,1) / 365,25) = 6689
C = A – INT (365,25 * B) = 305
E = INT (C / 30,61) = 9
F = INT (E / 14) = 0
R = B – 4716 + F = 1973
M = E – 1 – 12 * F = 8
D = C + U – INT (153 * E / 5) = 30

konto usunięte

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Ja używam daty w formacie Delphi - float o postaci "dzien.czesc_dnia".

Część "dzien" to liczba całkowita określająca nr dnia np. od 1970 roku. Część "czesc_dnia" to "frakcja" dnia - np. 06:00 to coś ok. 0.25

Dzieki temu data + k wyglada tak:


moja_data data_nowa = data_stara + static_cast<double>(k);


Ułatwia to zresztą wiele rzeczy - np. operacje na czasie w tej dacie zawartym.
Łukasz C.

Łukasz C. Senior Technical
Architect

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Piotr Likus:
Ja używam daty w formacie Delphi - float o postaci "dzien.czesc_dnia".
data julianska ma wiecej mozliwosci, bo nie masz ograniczenia roku 1970, a idea ogolnie ta sama
Jarosław Rybski

Jarosław Rybski Programista
C/C++/Python

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Nie ma co sobie życia utrudniać - wystarczy prosta klasa

class cDate
{
private:
int month;
int day;
int year;
static const int days[];
void incDay();
bool przestepnyRok( int _year ) const;
bool endMonth( int _day ) const;
public:
cDate(); // 1900.01.01
cDate( int y, int m, int d);
void addDays(int countDays);
};

i dalej
const int cDate::days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
bool cDate::przestepnyRok( int _year ) const
{
if ( _year % 400 == 0 || ( _year % 100 != 0 && _year % 4 == 0))
return true;

return false;
}
//----------
bool cDate::endMonth( int _day ) const
{
if ( month == 2 && przestepnyRok( year ))
return _day == 29;

return _day == days[ month ];
}
//----------
void cDate::addDays(int countDays)
{
for(int i = 0; i < countDays; i++)
{
incDay();
}
}
//----------
void cDate::incDay()
{
if (!endMonth( day ))
++day;
else
if ( month < 12 )
{
++month;
day = 1;
}
else
{
++year;
month = 1;
day = 1;
}
}
//----------

To będzie najprostsze rozwiązanie do zaimplementowaniaJarosław Rybski edytował(a) ten post dnia 22.12.09 o godzinie 10:05
Jakub L.

Jakub L. Programista

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Dni ogólnie duzo nie ma jak na wydajność komputerów, ale oranie liniowo nie wydaje mi się najlepszym pomysłem.

Podszedł bym do tego robiąc skoki o lata (dzielenie całkowite przez 365), później kroki o miesiąc i na końcu dzień, biorąc ewentualne korekty na lata przestępne.
Jarosław Rybski

Jarosław Rybski Programista
C/C++/Python

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Jakub L.:
Dni ogólnie duzo nie ma jak na wydajność komputerów, ale oranie liniowo nie wydaje mi się najlepszym pomysłem.

Podszedł bym do tego robiąc skoki o lata (dzielenie całkowite przez 365), później kroki o miesiąc i na końcu dzień, biorąc ewentualne korekty na lata przestępne.

Owszem jeśli mielibyśmy dodawać stulecia/tysiąclecia natomiast w pozostałych przypadkach to niech każdy już sobie odpowie
Szymon Kubisiak

Szymon Kubisiak Developer aplikacji
mobilnych Android

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Myślę że przeliczanie na unixtime nie jest najlepszym rozwiązaniem, gdyż zaczynają dochodzić sekundy przestępne z których część jest dodawana zupełnie arbitralnie decyzją komisji.

konto usunięte

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Istnieje bardzo dobra biblioteka do tego celu. To DateUtils. Przesunięcie o zadaną liczbę dni zajmuje się funkcja IncDay(const TDateTime AValue, const int ANumberOfDays = 1).

konto usunięte

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Mirosław Ślanda:
Istnieje bardzo dobra biblioteka do tego celu. To DateUtils. Przesunięcie o zadaną liczbę dni zajmuje się funkcja IncDay(const TDateTime AValue, const int ANumberOfDays = 1).

Albo cos bardziej znanego np. Boost Date Time.
Paweł Zubrycki

Paweł Zubrycki Proszę oferty tylko
z widełkami
płacowymi na co
najwyżej ...

Temat: [C++] przesuwanie dat o zadaną liczbę dni

Jak wyżej, myślę, że lepiej uzyc Boosta:
  
#include <boost/date_time/gregorian/gregorian.hpp>
#include <iostream>

int main(){
using namespace boost::posix_time;
using namespace boost::gregorian;
std::cout << "O ile dni przesunac? ";
long n;
std::cin >> n;
date d(day_clock::local_day());

std::cout << ( d + days(n) ) << std::endl;

return 0;
}
Paweł Zubrycki edytował(a) ten post dnia 15.01.10 o godzinie 00:17

Następna dyskusja:

Kodowanie dat w ASCII




Wyślij zaproszenie do