2015-09-16 11 views
14

Dlaczego Time.current jest równy parsowanym odpowiednikom?Dlaczego te dwa rodzaje danych są różne?

current = Time.current 
# Wed, 16 Sep 2015 17:10:56 CEST +02:00 
parsed = Time.zone.parse('16 Sep 2015 17:10:56') 
# Wed, 16 Sep 2015 17:10:56 CEST +02:00 
current == parsed 
# false <= What ?! 
current.to_i == parsed.to_i 
# true 
Ticket.create(datetime: current) 
# ... 
Ticket.find_by_datetime(parsed) 
# nil <= Why ?! 

ja rzeczywiście kłopoty z tym w aplikacji Ruby on Rails, gdzie staram się znaleźć zapis w oparciu o atrybut datetime, który został przeanalizowany, jak pokazano na ostatnich wierszy.

Naprawdę nie rozumiem. Strefy czasowe są takie same, czasy są takie same do sekund. Co tu się dzieje?

Ponadto, w jaki sposób powinienem kontynuować wyszukiwanie rekordu na podstawie przeanalizowanej daty i godziny?

+5

Twój zegar komputerowy prawdopodobnie ma dokładność pod sekundę ;-) (wskazówka: 'to_f') – Stefan

+0

Dzięki! OK, więc przeanalizowana data i godzina nie ma dokładności pod sekundę. Ale co mam zrobić, aby pobrać rekord w bazie danych? –

+1

Skróć atrybut do całych sekund przed zapisaniem go do bazy danych lub podaj zakres, który obejmuje całą sekundę: 'Ticket.where (datetime: parsowany ... parsowany + 1)' – Stefan

Odpowiedz

5

Dziękuję wszystkim za pomoc. Mam nadzieję, że nie masz nic przeciwko, ale ponieważ fragmenty ostatecznej odpowiedzi są rozproszone w wielu odpowiedziach, odpowiem na moje własne pytanie, opierając się na tym, co powiedziałeś.

A więc dlaczego daty są różne, to z powodu braku milisekund w sparsowanych datach. Jak wspomniał @dimakura.

current.to_f #=> 1442417032.6567826 
parsed.to_f #=> 1442417032.0 

Następnie odpowiedź na pytanie, w jaki sposób możemy pobrać rekord Ticket na podstawie przeanalizowanych datetime.

Po pierwsze ważne jest, aby wiedzieć, że będzie to istotne tylko dla PostgreSQL (mój przypadek) lub innych baz danych, które faktycznie przechowują milisekundy. Dzięki @sjagr za wzmiankę o tym.

Musimy więc zapytać o zakresie od analizowany do analizowany + 1 sekundę, jak @Stefan wyjaśnił:

Ticket.where(datetime: parsed...parsed+1).first 

A jeśli mamy kontrolę nad tworzeniem biletowa, możemy również usunąć precyzji milisekundy przed zapisywanie bazy danych. Dzięki @sjagr za zapewnienie łatwego sposobu na zrobienie tego.

current = Time.current 
Ticket.create(datetime: current.change(usec: 0)) 

Dziękuję wszystkim!

21

one nie powinny być takie same:

current.to_f #=> 1442417032.6567826 
parsed.to_f #=> 1442417032.0 

Podczas analizowania, pominięcia milisekund.

+1

Czy mógłbyś następnie rozwinąć sposób, w jaki możemy pobrać rekord w DB na podstawie sparsowanego łańcucha, który nie ma dokładności milisekundy? –

+1

@JeremyF. Czy możesz wydrukować 'ticket.datetime.to_f'? – dimakura

+0

1442416256.115874 –

3

To dlatego, że nie są równe, różnią się one częściami drugiego. To, co widzisz na konsoli, jest wynikiem metody o tej nazwie, która domyślnie upuszcza dowolne części pod-drugie.