Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

różnica dat C# vs PL/SQL

83 views
Skip to first unread message

Jakub Owczarski

unread,
Oct 25, 2009, 7:20:17 PM10/25/09
to
Witam.
Mam pewną bazę gdzie data trzymana jest w polu number. Po szybkim
sprawdzeniu (w oracle) wyszło mi, że jest to liczba dni od 0001-01-02.
Teraz potrzebowałem też pomieszać w tym na poziomie C# no i okazuje
się, że dostaję różne wyniki.
Testuję w oracle:
select to_date('2009-10-25','yyyy-mm-dd') - to_date('0001-01-02','yyyy-
mm-dd') ts from dual
dostaję ts = 733705

w C#:
TimeSpan ts = new TimeSpan();
ts = new DateTime(2009, 10, 25).Date - new DateTime(1, 1, 2).Date;
dostaję ts = 733703

Czyli dwa dni różnicy. Ma ktoś pomysł o co tu chodzi? Skąd się biora
te dwa dni różnicy?

Pozdrawiam.

Mateusz Ludwin

unread,
Oct 26, 2009, 11:40:35 AM10/26/09
to
Jakub Owczarski wrote:

> Czyli dwa dni r�nicy. Ma kto� pomys� o co tu chodzi? Sk�d si� biora
> te dwa dni r�nicy?

Od urodzin Jezusa mieli�my par� reform kalendarza :>
--
Mateusz Ludwin mateuszl [at] gmail [dot] com

Wiktor S.

unread,
Oct 26, 2009, 12:28:26 PM10/26/09
to
> w C#:
> TimeSpan ts = new TimeSpan();
> ts = new DateTime(2009, 10, 25).Date - new DateTime(1, 1, 2).Date;
> dostajďż˝ ts = 733703

> Czyli dwa dni r�nicy. Ma kto� pomys� o co tu chodzi? Sk�d si� biora
> te dwa dni r�nicy?

Pewnie z b��du w jednym albo w drugim, ale nikt si� nie spodziewa po
nieastronomicznym oprogramowaniu prawid�owej obs�ugi kosmicznych dat.
We� sobie te dwa dni poprawki i zobacz, czy r�nica si� nie rozje�d�a w
zakresie powiedzmy lat 1900..2100.


--
Azarien

Paweł Kierski

unread,
Oct 27, 2009, 4:52:50 AM10/27/09
to

Bo to niejawnie wartości z po za zakresu. Jeśli nie znormalizujesz dat
np. do dni juliańskich, to nic z tego nie będzie. Równie dobrze możesz
porównywć daty z kalendarza Majów i prawosławnego.

Po drodze było co najmniej przejście z kalendarza juliańskiego na
gregoriański, które "zniknęło" kilka dni. Na dodatek ekstrapolując
wstecz regułę wyznaczania dni przestępnych z kalendarza gregoriańskiego
przed reformę masz dodatkowe kilka dni różnicy (np. juliański 1200 był
przestępny, choć wg reguły gregoriańskiej nie byłby).

--
Paweł Kierski
ne...@pkierski.net

Wiktor S.

unread,
Oct 27, 2009, 8:53:37 AM10/27/09
to
> Po drodze było co najmniej przejście z kalendarza juliańskiego na
> gregoriański,

Które "nie wiadomo kiedy było", bo następowało w różnych krajach różnie w
okresie 1582-1926. Jakiekolwiek daty w tym okresie muszą brać pod uwagę
państwo.

> które "zniknęło" kilka dni.

Dlatego nie wolno zakładać, że jakikolwiek system do współczesnego użytku
(jak baza danych) będzie prawidłowo operować na historycznych datach. Jak
potrzebne są takie daty, to się robi własną obsługę kalendarza, i trzeba się
niestety zagłębiać we wszystkie niuanse..

> Na dodatek ekstrapolując
> wstecz regułę wyznaczania dni przestępnych z kalendarza
> gregoriańskiego przed reformę masz dodatkowe kilka dni różnicy (np.
> juliański 1200 był przestępny, choć wg reguły gregoriańskiej nie
> byłby).

No jeżeli bierzemy pod uwagę przesunięcie daty, to jednocześnie należy
zmienić regułę lat przestępnych. Dochodzi jeszcze fakt, że Rzymianie trochę
dowolnie podchodzili sobie do lat przestępnych, więc liczenie dat w roku 1 z
dokładnością co do dnia traci sens: dokładna rachuba została utracona.


--
Azarien

Jakub Owczarski

unread,
Oct 27, 2009, 1:11:28 PM10/27/09
to
On Oct 27, 12:53 pm, "Wiktor S." <wswiktor&poczta,f...@no.spam> wrote:

> Dlatego nie wolno zakładać, że jakikolwiek system do współczesnego użytku
> (jak baza danych) będzie prawidłowo operować na historycznych datach. Jak
> potrzebne są takie daty, to się robi własną obsługę kalendarza, i trzeba się
> niestety zagłębiać we wszystkie niuanse..

Tylko, że to jest baza która już istnieje, daty są w niej
przechowywane jako number.
Nie ma możliwości zapytać twórców jak oni to liczyli.
"Organoleptycznie" stwierdziłem, że jest to liczba dni od
"0001-01-02".
Jak myślicie czy jest jakaś gwarancja, że oracle w każdym następnym
wydaniu zachowa ten sposób liczenia który ma teraz?
Najlepiej by było oczywiście dowiedzieć się jak to liczyli ci którzy
bazę tworzyli ale niestety jest to niemożlwe.

Pzdr.

Wiktor S.

unread,
Oct 27, 2009, 3:43:05 PM10/27/09
to
> Tylko, �e to jest baza kt�ra ju� istnieje, daty s� w niej
> przechowywane jako number.
> Nie ma mo�liwo�ci zapyta� tw�rc�w jak oni to liczyli.
> "Organoleptycznie" stwierdzi�em, �e jest to liczba dni od
> "0001-01-02".

Bo "tak ci wysz�o", ale z tego co widzisz - nie mo�esz tak odleg�ym datom
ufaďż˝.

> Jak my�licie czy jest jaka� gwarancja, �e oracle w ka�dym nast�pnym
> wydaniu zachowa ten spos�b liczenia kt�ry ma teraz?

Oracle nie ma tu nic do rzeczy - bo do przechowywania daty ma typ DATETIME
(czy jak tam), a je�li w bazie data jest jako liczba - to jest to podej�cie
niestandardowe i prawdopodobnie widzimisi� tw�rcy bazy.

Ale:

przeczytaj sobie http://en.wikipedia.org/wiki/Julian_day
i sp�jrz na tabelk�: warto�ci w okolicach 733707 to system "Rata Die", i z
definicji liczy si� to jako RD = floor(JD - 1721424.5), gdzie wz�r na JD
podany jest ni�ej na tej samej stronie.
Je�li nie chcesz takiego b��du o dzie� czy dwa, licz dok�adnie wed�ug wzor�w
(jako godzin� przyjmij sobie po�udnie albo godzin� z bazy, je�li jest).

--
Azarien


Jakub Owczarski

unread,
Oct 28, 2009, 4:31:56 AM10/28/09
to
On Oct 27, 7:43 pm, "Wiktor S." <wswiktor&poczta,f...@no.spam> wrote:

> Oracle nie ma tu nic do rzeczy - bo do przechowywania daty ma typ DATETIME

> (czy jak tam), a jeśli w bazie data jest jako liczba - to jest to podejście
> niestandardowe i prawdopodobnie widzimisię twórcy bazy.

No jednak ma, mógł by teoretycznie np. w kolejnym wydaniu stwierdzić,
że teraz będzie liczyć inaczej(np tak jak wspomniany python czy C#).
No ale to nie ważne bo

> przeczytaj sobiehttp://en.wikipedia.org/wiki/Julian_day

przeczytałem i to chyba faktycznie to jest Rata Die, a tylko
przypadkiem wyszło mi, że data - 0001-01-02.
Dzięki!

Teraz wygląda to tak:
SELECT FLOOR( ( TO_CHAR (SYSDATE, 'j')
+ ( (TO_CHAR (SYSDATE, 'hh24') - 12) / 24)
+ (TO_CHAR (SYSDATE, 'mi') / 1440)
+ (TO_CHAR (SYSDATE, 'ss') / 86400))
- 1721424.5)
RD
FROM DUAL

Dzięki, pozdrawiam

0 new messages