it-swarm-tr.com

Python'da datetime.time dizinine N saniye eklemenin standart yolu nedir?

Python'da bir datetime.time değeri göz önüne alındığında, buna bir tamsayı saniye eklemek için standart bir yol var, örneğin 11:34:59 + 3 = 11:35:02, örneğin?

Bu açık fikirler işe yaramaz:

>>> datetime.time(11, 34, 59) + 3
TypeError: unsupported operand type(s) for +: 'datetime.time' and 'int'
>>> datetime.time(11, 34, 59) + datetime.timedelta(0, 3)
TypeError: unsupported operand type(s) for +: 'datetime.time' and 'datetime.timedelta'
>>> datetime.time(11, 34, 59) + datetime.time(0, 0, 3)
TypeError: unsupported operand type(s) for +: 'datetime.time' and 'datetime.time'

Sonunda bunun gibi fonksiyonlar yazdım:

def add_secs_to_time(timeval, secs_to_add):
    secs = timeval.hour * 3600 + timeval.minute * 60 + timeval.second
    secs += secs_to_add
    return datetime.time(secs // 3600, (secs % 3600) // 60, secs % 60)

Yine de bunu yapmanın daha kolay bir yolunu özlüyorum olduğumu düşünmeden edemiyorum.

İlgili

315
Paul Stephenson

Tam datetime değişkenlerini timedelta ile kullanabilir ve kukla bir tarih belirleyerek daha sonra sadece zaman değerini elde etmek için time kullanarak.

Örneğin:

import datetime
a = datetime.datetime(100,1,1,11,34,59)
b = a + datetime.timedelta(0,3) # days, seconds, then other fields.
print a.time()
print b.time()

iki saniyede üç saniye aralıklarla sonuçlanır:

11:34:59
11:35:02

Ayrıca daha okunaklı olmayı tercih edebilirsiniz

b = a + datetime.timedelta(seconds=3)

eğer bu kadar meyilliysen.


Bunu yapabilen bir işlevin peşindeyseniz, aşağıdaki addSecs öğesini kullanarak bakabilirsiniz:

import datetime

def addSecs(tm, secs):
    fulldate = datetime.datetime(100, 1, 1, tm.hour, tm.minute, tm.second)
    fulldate = fulldate + datetime.timedelta(seconds=secs)
    return fulldate.time()

a = datetime.datetime.now().time()
b = addSecs(a, 300)
print a
print b

Bu çıktılar:

 09:11:55.775695
 09:16:55
445
paxdiablo

Buradaki diğer kişilerin belirttiği gibi, tam tarih boyunca tam tarih nesnelerini kullanabilirsiniz:

sometime = get_some_time() # the time to which you want to add 3 seconds
later = (datetime.combine(date.today(), sometime) + timedelta(seconds=3)).time()

Ancak, tam tarih nesnelerinin neden gerekli olduğunu açıklamaya değeceğini düşünüyorum. Saat 23: 00'e 2 saat eklersem neler olacağını düşünün Doğru davranış nedir? Bir istisna, çünkü saat 11: 59'dan daha büyük bir zamanınız olamaz. Geri sarmalı mı?

Farklı programcılar farklı şeyler bekleyeceklerdir, bu nedenle seçtikleri sonuç her ne kadar birçok insanı şaşırtacaktır. Daha da kötüsü, programcılar başlangıçta test ettiklerinde iyi çalışan bir kod yazarlar ve daha sonra beklenmedik bir şey yaparak daha sonra kırılırlardı. Bu çok kötü, bu yüzden zaman nesnelerine zaman çizelgesi nesneleri eklemenize izin verilmiyor.

45
Eli Courtwright

Küçük bir şey, varsayılan değeri saniyeler boyunca geçersiz kılmak için netlik sağlayabilir

>>> b = a + datetime.timedelta(seconds=3000)
>>> b
datetime.datetime(1, 1, 1, 12, 24, 59)
19
unmounted

@Pax Diablo, boyunca @ tam günleri kullanma önerisi için @ bvmou ve @Arachnid. Datetime.time nesnelerini harici bir kaynaktan kabul etmem gerekiyorsa, bu alternatif bir add_secs_to_time() işlevi gibi görünüyor:

def add_secs_to_time(timeval, secs_to_add):
    dummy_date = datetime.date(1, 1, 1)
    full_datetime = datetime.datetime.combine(dummy_date, timeval)
    added_datetime = full_datetime + datetime.timedelta(seconds=secs_to_add)
    return added_datetime.time()

Bu ayrıntılı kod bu tek linere sıkıştırılabilir:

(datetime.datetime.combine(datetime.date(1, 1, 1), timeval) + datetime.timedelta(seconds=secs_to_add)).time()

ama sanırım yine de kodu açıklığa kavuşturmak için bir fonksiyona dahil etmek isterdim.

11
Paul Stephenson

Projenize başka bir dosya/bağımlılık eklemeye değerse, daha önce datetime.time u aritmetik hale getirme özelliğine sahip küçük bir sınıf yazdım. Gece yarısını geçtiğinizde sıfıra sarar. Şimdi, “Saat kaç, şimdiden 24 saat olacak” gün ışığından yararlanma saati, artık saniyeler, geçmiş zaman dilimi değişiklikleri vb. Gibi birçok köşe davası var. Ama bazen basit bir davaya gerçekten ihtiyaç duyuyorsunuz ve bu böyle olacak.

Örneğiniz yazılı olurdu:

>>> import datetime
>>> import nptime
>>> nptime.nptime(11, 34, 59) + datetime.timedelta(0, 3)
nptime(11, 35, 2)

nptime, datetime.time ürününden devralır, bu nedenle bu yöntemlerden herhangi birinin de kullanılabilir olması gerekir.

PyPi'den nptime ("pedantik olmayan zaman") veya GitHub'da bulunabilir: https://github.com/tgs/nptime

8
rescdsk

Hangi ünitenin kullanıldığı belli değil çünkü datetime 'ye sayı ekleyemezsiniz: saniye, saat, hafta ...

Tarih ve saat içeren işlemler için timedelta sınıfı var. datetime eksi datetimetimedelta verir, datetime artı timedelta verir datetime verir, iki datetime nesnesi eklenemez, ancak iki timedelta olabilir.

Kaç saniye eklemek istediğiniz timedelta nesnesini oluşturun ve datetime nesnesine ekleyin:

>>> from datetime import datetime, timedelta
>>> t = datetime.now() + timedelta(seconds=3000)
>>> print(t)
datetime.datetime(2018, 1, 17, 21, 47, 13, 90244)

C++ 'da da aynı kavram var: std::chrono::duration.

5
user2387567

Bütünlük uğruna, işte arrow (Python için daha iyi tarihler ve saatler) ile yapmanın yolu:

sometime = arrow.now()
abitlater = sometime.shift(seconds=3)
3
Bart Van Loon

datetime.datetime ürününe datetime.timedelta eklemeyi deneyin. Yalnızca zaman bölümünü istiyorsanız, elde etmek için elde edilen datetime.datetime nesnesindeki time() yöntemini çağırabilirsiniz.

1
Nick Johnson

Eski soru, ama saat dilimleri işleyen bir işlevi yerine getireceğimi düşündüm. Kilit parçalar datetime.time nesnesinin tzinfo niteliğini birleştirme işlemine geçiriyor ve ardından kukla tarihte timetz() yerine time() kullanarak. Bu cevap kısmen buradaki diğer cevaplardan esinlenmiştir.

def add_timedelta_to_time(t, td):
    """Add a timedelta object to a time object using a dummy datetime.

    :param t: datetime.time object.
    :param td: datetime.timedelta object.

    :returns: datetime.time object, representing the result of t + td.

    NOTE: Using a gigantic td may result in an overflow. You've been
    warned.
    """
    # Create a dummy date object.
    dummy_date = date(year=100, month=1, day=1)

    # Combine the dummy date with the given time.
    dummy_datetime = datetime.combine(date=dummy_date, time=t, tzinfo=t.tzinfo)

    # Add the timedelta to the dummy datetime.
    new_datetime = dummy_datetime + td

    # Return the resulting time, including timezone information.
    return new_datetime.timetz()

Ve burada gerçekten basit bir test senaryosu sınıfı (yerleşik unittest kullanarak):

import unittest
from datetime import datetime, timezone, timedelta, time

class AddTimedeltaToTimeTestCase(unittest.TestCase):
    """Test add_timedelta_to_time."""

    def test_wraps(self):
        t = time(hour=23, minute=59)
        td = timedelta(minutes=2)
        t_expected = time(hour=0, minute=1)
        t_actual = add_timedelta_to_time(t=t, td=td)
        self.assertEqual(t_expected, t_actual)

    def test_tz(self):
        t = time(hour=4, minute=16, tzinfo=timezone.utc)
        td = timedelta(hours=10, minutes=4)
        t_expected = time(hour=14, minute=20, tzinfo=timezone.utc)
        t_actual = add_timedelta_to_time(t=t, td=td)
        self.assertEqual(t_expected, t_actual)


if __== '__main__':
    unittest.main()
0
blthayer