Czy jest różnica między " = = "A " is"?

Odpowiedzi na to pytanie są wysiłkiem społeczności. Edytuj istniejące odpowiedzi, aby poprawić ten post. Obecnie nie przyjmuje nowych odpowiedzi ani interakcji.

Moje Google-fu zawiodło mnie.

W Pythonie, czy poniższe dwa testy równości są równoważne?

n = 5
# Test one.
if n == 5:
    print 'Yay!'

# Test two.
if n is 5:
    print 'Yay!'

Czy to prawda dla obiektów, w których porównujesz instancje (a list powiedzmy)?

Ok, więc taki rodzaj odpowiedzi na moje pytanie:

L = []
L.append(1)
if L == [1]:
    print 'Yay!'
# Holds true, but...

if L is [1]:
    print 'Yay!'
# Doesn't.

Więc == testuje wartość gdzie is testuje, czy są tym samym obiektem?

Author: martineau, 2008-09-25

14 answers

is zwróci True Jeśli dwie zmienne wskazują na ten sam obiekt, {[5] } jeśli obiekty, do których odnoszą się zmienne, są równe.

>>> a = [1, 2, 3]
>>> b = a
>>> b is a 
True
>>> b == a
True

# Make a new copy of list `a` via the slice operator, 
# and assign it to variable `b`
>>> b = a[:] 
>>> b is a
False
>>> b == a
True

W Twoim przypadku drugi test działa tylko dlatego, że Python buforuje małe obiekty całkowite, co jest szczegółem implementacji. Dla większych liczb całkowitych to nie działa:

>>> 1000 is 10**3
False
>>> 1000 == 10**3
True

To samo dotyczy liter ciągów:

>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True

Proszę zobaczyćto pytanie również.

 986
Author: Torsten Marek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-05 20:47:38

Istnieje prosta zasada mówiąca, kiedy należy stosować == lub is.

  • == jest dla równość wartości . Użyj go, gdy chcesz wiedzieć, czy dwa obiekty mają tę samą wartość.
  • is oznacza równość odniesienia. Użyj go, gdy chcesz wiedzieć, czy dwa odniesienia odnoszą się do tego samego obiektu.

Ogólnie rzecz biorąc, kiedy porównujesz coś z prostym typem, Zwykle sprawdzasz równość wartości, więc należy użyć ==. Na przykład, intencją twojego przykładu jest prawdopodobnie sprawdzenie, czy x ma wartość równą 2 (==), a nie czy x odnosi się dosłownie do tego samego obiektu co 2.


Coś jeszcze do odnotowania: ze względu na sposób, w jaki implementacja CPython reference działa, otrzymasz nieoczekiwane i niespójne wyniki, jeśli błędnie użyjesz is do porównania równości referencji na liczbach całkowitych:

>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False

Tego się spodziewaliśmy: a i b mają tej samej wartości, ale są odrębnymi bytami. Ale co z tym?

>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True

Jest to niezgodne z wcześniejszym wynikiem. Co tu się dzieje? Okazuje się, że referencyjna implementacja Pythona buforuje obiekty całkowite w zakresie -5..256 jako instancje singleton ze względu na wydajność. Oto przykład demonstrujący to:

>>> for i in range(250, 260): a = i; print "%i: %s" % (i, a is int(str(i)));
... 
250: True
251: True
252: True
253: True
254: True
255: True
256: True
257: False
258: False
259: False

Jest to kolejny oczywisty powód, aby nie używać is: zachowanie jest pozostawione do implementacji, gdy błędnie używasz go dla wartości równość.

 333
Author: John Feminella,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-03 02:09:38

Czy jest różnica między == a is w Pythonie?

Tak, mają bardzo ważną różnicę.

==: sprawdzanie równości-semantyka polega na tym, że równoważne obiekty (które niekoniecznie są tym samym obiektem) będą testowane jako równe. Jak mówi dokumentacja :

Operatory , ==, >=,

is: check for identity-the semantyka polega na tym, że obiekt (przechowywany w pamięci) jest obiektem. Ponownie, dokumentacja mówi :

Operatory is i is not sprawdzają tożsamość obiektu: x is y jest prawdą wtedy i tylko wtedy, gdy x i y są tym samym obiektem. Tożsamość obiektu jest określone za pomocą funkcji id(). x is not y daje odwrotność wartość prawdy.

Tak więc sprawdzanie tożsamości jest tym samym, co sprawdzanie równości ID obiektów. Że is,

a is b

Jest tym samym co:

id(a) == id(b)

Gdzie {[16] } jest wbudowaną funkcją zwracającą liczbę całkowitą, która "jest gwarantowana jako unikalna wśród jednocześnie istniejących obiektów" (zobacz help(id)) i gdzie a i b są dowolnymi dowolnymi obiektami.

Inne Wskazówki Użytkowania

Powinieneś użyć tych porównań do ich semantyki. Użyj is, aby sprawdzić tożsamość i ==, aby sprawdzić równość.

Więc ogólnie używamy is, aby sprawdzić tożsamość. To jest zwykle przydatne, gdy sprawdzamy obiekt, który powinien istnieć tylko raz w pamięci, określany w dokumentacji jako "singleton".

Przypadki użycia dla is obejmują:

  • None
  • wartości enum (przy użyciu Enum z modułu enum)
  • Zwykle Moduły
  • Zwykle obiekty klasy wynikające z definicji klasy
  • Zwykle obiekty funkcyjne wynikające z definicji funkcji
  • Wszystko inne, co powinno istnieć tylko raz w pamięć (wszystkie singletony, ogólnie)
  • konkretny obiekt, który chcesz przez tożsamość

Typowe przypadki użycia dla == obejmują:

  • liczby, łącznie z liczbami całkowitymi
  • struny
  • listy
  • zestawy
  • słowniki
  • niestandardowe mutable objects
  • inne wbudowane niezmienne obiekty, w większości przypadków

Ogólny przypadek użycia, ponownie, dla ==, jest obiektem, który chcesz, może nie być tym samym obiektem, zamiast może to być odpowiednik jeden

PEP 8 kierunków

PEP 8, oficjalny przewodnik po stylach Pythona dla biblioteki standardowej wymienia również dwa przypadki użycia dla is:

Porównania do singletonów jak None powinny być zawsze wykonywane is lub is not, Nigdy operatorów równości.

Także, uważaj na pisanie if x kiedy naprawdę masz na myśli if x is not None -- na przykład podczas testowania, czy zmienna lub argument domyślnie None na Ustaw na inną wartość. Druga wartość może mieć typ (taki jako kontener), które mogą być fałszywe w kontekście logicznym!

Wnioskowanie równości z tożsamości

Jeśli is jest prawdą, równość może Zwykle być wywnioskowana - logicznie, jeśli obiekt jest sam w sobie, to powinien testować jako jego odpowiednik.

W większości przypadków ta logika jest prawdziwa, ale opiera się na implementacji specjalnej metody __eq__. Jak mówią docs

Domyślne zachowanie porównywania równości (== i !=) opiera się na tożsamość przedmiotów. Stąd porównanie równości instancji z tą samą tożsamością wynika równość, a równość instancje o różnych tożsamościach powodują nierówność. A motywacją do tego domyślnego zachowania jest pragnienie, aby wszystkie obiekty powinien być refleksyjny (tzn. x jest Y oznacza x = = y).

I w trosce o spójność, zaleca:

Porównanie równości powinno być refleksyjne. Innymi słowy, identyczne obiekty powinny być równe:

x is y implikuje x == y

Widzimy, że jest to domyślne zachowanie dla obiektów niestandardowych:

>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)

Contrapositive jest również zwykle prawdziwe - jeśli coś testuje się jako nie równe, zwykle można wywnioskować, że nie są one tym samym obiektem.

Ponieważ testy równości można dostosować, wniosek ten nie zawsze jest prawdziwy dla wszystkich typy.

Wyjątek

Godnym uwagi wyjątkiem jest nan - zawsze sprawdza się jako nie równy sobie:

>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan           # !!!!!
False

Sprawdzanie tożsamości może być znacznie szybsze niż sprawdzanie równości (które może wymagać rekurencyjnego sprawdzania członków).

Ale nie można go zastąpić równością, gdzie można znaleźć więcej niż jeden obiekt jako równoważny.

Zauważ, że porównywanie równości list i krotek zakłada, że tożsamość obiektów jest równa (ponieważ jest to szybka kontrola). Może to tworzyć sprzeczności, jeśli logika jest niespójna - tak jak dla nan:

>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True

Przestroga:

Pytanie próbuje użyć is do porównania liczb całkowitych. Nie należy zakładać, że instancja liczby całkowitej jest tą samą instancją co instancja uzyskana przez inne odniesienie. Ta historia wyjaśnia dlaczego.

Komentator miał kod, który opierał się na fakcie, że małe liczby całkowite (od -5 do 256 włącznie) są singletonami w Pythonie, zamiast sprawdzanie równości.

To może prowadzić do podstępnych błędów. Miałem jakiś kod, który sprawdzał, czy a jest b, który działał tak, jak chciałem, ponieważ a i b są zazwyczaj małymi liczbami. Błąd pojawił się dopiero dzisiaj, po sześciu miesiącach produkcji, ponieważ a i b były na tyle duże, że nie mogły być buforowane. - gwg

To działało w rozwoju. Mógł przejść kilka testów.

I działało w produkcji-dopóki kod nie sprawdzał liczby całkowitej większej niż 256, w którym to momencie nie udało się w produkcji.

Jest to błąd produkcyjny, który mógł zostać złapany w przeglądaniu kodu lub ewentualnie za pomocą sprawdzania stylów.

Pozwól, że podkreślę: nie używaj is do porównywania liczb całkowitych.

 39
Author: Aaron Hall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-10 18:31:09

== określa, czy wartości są równe, podczas gdy is określa, czy są dokładnie tym samym obiektem.

 35
Author: stephenbayer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-27 12:36:36

Jaka jest różnica między is a ==?

== i is są różne porównania! Jak już powiedzieli inni:

  • == porównuje wartości obiektów.
  • is porównuje odniesienia do obiektów.

W Pythonie nazwy odnoszą się do obiektów, na przykład w tym przypadku value1 i value2 odnoszą się do instancji int przechowującej wartość 1000:

value1 = 1000
value2 = value1

Tutaj wpisz opis obrazka

Ponieważ value2 odnosi się do tego samego obiektu is i == daTrue:

>>> value1 == value2
True
>>> value1 is value2
True
W poniższym przykładzie nazwy value1 i value2 odnoszą się do różnych instancji int, nawet jeśli oba zawierają tę samą liczbę całkowitą:
>>> value1 = 1000
>>> value2 = 1000

Tutaj wpisz opis obrazka

Ponieważ ta sama wartość (liczba całkowita) jest przechowywana == będzie True, dlatego często nazywa się ją "porównaniem wartości". Jednak is zwróci False ponieważ są to różne obiekty:

>>> value1 == value2
True
>>> value1 is value2
False

Kiedy użyć którego?

Ogólnie is jest znacznie szybszym porównanie. Dlatego CPython buforuje (a może reuses byłoby lepszym określeniem) pewne obiekty, takie jak małe liczby całkowite, niektóre łańcuchy znaków itp. Ale to powinno być traktowane jako szczegóły implementacji , które mogą (nawet jeśli mało prawdopodobne) zmienić się w dowolnym momencie bez ostrzeżenia.

Powinieneś używać tylko is jeśli:

  • Chcesz sprawdzić, czy dwa obiekty są rzeczywiście tym samym obiektem (nie tylko tą samą "wartością"). Jednym z przykładów może być, jeśli ty używasz obiekt Singletona jako stały.

  • Chcesz porównać wartość do Pythona stałej. Stałe w Pythonie to:

    • None
    • True1
    • False1
    • NotImplemented
    • Ellipsis
    • __debug__
    • klasy (na przykład int is int lub int is float)
    • mogą istnieć dodatkowe stałe we wbudowanych modułach lub modułach innych firm. Na przykład np.ma.masked od NumPy moduł)

W w każdym innym przypadku należy użyć == aby sprawdzić równość.

Czy Mogę dostosować zachowanie?

Jest pewien aspekt ==, który nie został wymieniony jeszcze w innych odpowiedziach: jest częścią Pythons "model danych" . Oznacza to, że jego zachowanie można dostosować za pomocą __eq__ metoda. Na przykład:

class MyClass(object):
    def __init__(self, val):
        self._value = val

    def __eq__(self, other):
        print('__eq__ method called')
        try:
            return self._value == other._value
        except AttributeError:
            raise TypeError('Cannot compare {0} to objects of type {1}'
                            .format(type(self), type(other)))

Jest to tylko sztuczny przykład, aby zilustrować, że metoda jest naprawdę nazwa:

>>> MyClass(10) == MyClass(10)
__eq__ method called
True

Zauważ, że domyślnie (jeśli żadna inna implementacja __eq__ nie może być znaleziona w klasie lub superklasach) __eq__ używa is:

class AClass(object):
    def __init__(self, value):
        self._value = value

>>> a = AClass(10)
>>> b = AClass(10)
>>> a == b
False
>>> a == a

Dlatego ważne jest, aby zaimplementować __eq__ jeśli chcesz "więcej" niż tylko porównywanie referencji dla klas niestandardowych!

Z drugiej strony nie można dostosować is kontroli. Zawsze będzie porównywać tylko , jeśli masz to samo odniesienie.

Czy te porównania zawsze zwrócą boolean?

Ponieważ __eq__ może być ponownie zaimplementowany lub nadpisany, nie ogranicza się do zwracania True lub False. To może zwrócić cokolwiek (ale w większości przypadków powinno zwrócić wartość logiczną!).

Na przykład z tablicami NumPy == zwróci tablicę:

>>> import numpy as np
>>> np.arange(10) == 2
array([False, False,  True, False, False, False, False, False, False, False], dtype=bool)

Ale is kontrole zawsze wrócą True lub False!


1 jak wspomniał Aaron Hall w komentarzach:

Ogólnie nie powinieneś robić żadnych is True lub is False kontroli ponieważ zwykle używa się tych "sprawdzeń" w kontekście, który domyślnie konwertuje warunek na wartość logiczną (na przykład w instrukcji if). Tak więc wykonanie porównania is True i Ukryty boolean cast wykonuje więcej pracy niż tylko wykonanie boolean cast - i ograniczasz się do booleanów (co nie jest uważane za pythoniczne).

Jak PEP8 wspomina:

Nie porównuj wartości logicznych do True lub False używając ==.

Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:
 22
Author: MSeifert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

zupełnie inne . is sprawdza tożsamość obiektu, podczas gdy == sprawdza równość(pojęcie, które zależy od dwóch typów operandów).

To tylko szczęśliwy zbieg okoliczności, że "is" wydaje się działać poprawnie z małymi liczbami całkowitymi (np. 5 == 4+1). Jest tak, ponieważ CPython optymalizuje przechowywanie liczb całkowitych w zakresie (-5 do 256), tworząc z nich singletony. Zachowanie to jest całkowicie zależne od implementacji i nie gwarantuje zachowania pod wszelkiego rodzaju drobnych operacji transformacyjnych.

Na przykład Python 3.5 również tworzy krótkie stringi singletonów, ale ich przecięcie zakłóca to zachowanie:

>>> "foo" + "bar" == "foobar"
True
>>> "foo" + "bar" is "foobar"
True
>>> "foo"[:] + "bar" == "foobar"
True
>>> "foo"[:] + "bar" is "foobar"
False
 20
Author: Dan Lenski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-10 15:14:22

Https://docs.python.org/library/stdtypes.html#comparisons

is testy na tożsamość == testy równości

Każda (mała) liczba całkowita jest mapowana do pojedynczej wartości, więc każde 3 jest identyczne i równe. Jest to szczegół implementacji, a nie część specyfikacji języka

 10
Author: mmaibaum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-13 10:02:19

Twoja odpowiedź jest prawidłowa. Operator is porównuje tożsamość dwóch obiektów. Operator == porównuje wartości dwóch obiektów.

Tożsamość obiektu nigdy nie zmienia się po jego utworzeniu; możesz myśleć o nim jako o adresie obiektu w pamięci.

Możesz kontrolować zachowanie porównywania wartości obiektu poprzez zdefiniowanie metody __cmp__ lub metodyrich comparison , takiej jak __eq__.

 6
Author: Dave Webb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-13 09:24:18

Spójrz na pytanie o przepełnienie stosu Operator Pythona " is " zachowuje się nieoczekiwanie z liczbami całkowitymi.

Sprowadza się to głównie do tego, że "is" sprawdza, czy są one tym samym obiektem, a nie tylko równym sobie (liczby poniżej 256 są szczególnym przypadkiem).

 4
Author: cobbal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:38

W skrócie, is sprawdza, czy dwa odniesienia wskazują na ten sam obiekt, czy nie.== sprawdza, czy dwa obiekty mają tę samą wartość, czy nie.

a=[1,2,3]
b=a        #a and b point to the same object
c=list(a)  #c points to different object 

if a==b:
    print('#')   #output:#
if a is b:
    print('##')  #output:## 
if a==c:
    print('###') #output:## 
if a is c:
    print('####') #no output as c and a point to different object 
 3
Author: suvojit_007,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-29 20:17:41

Jak powiedział John Feminella, większość czasu będziesz używać = = i != ponieważ twoim celem jest porównanie wartości. Chciałbym tylko skategoryzować co byś robił przez resztę czasu:

Istnieje tylko jedna instancja NoneType, tzn. None jest singletonem. W konsekwencji foo == None i foo is None oznaczają to samo. Jednak test is jest szybszy, a konwencja Pythoniczna ma używać foo is None.

Jeśli robisz jakąś introspekcję lub robisz coś ze śmieciami lub sprawdzasz, czy Twój niestandardowy gadżet do internowania ciągów działa lub coś takiego, prawdopodobnie masz przypadek użycia dla foo jest bar.

True I False są również (teraz) singletonami, ale nie ma przypadków użycia dla foo == True i nie ma przypadków użycia dla foo is True.

 2
Author: John Machin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-06 08:50:52

Większość z nich już odpowiedziała na to pytanie. Tylko jako dodatkowa uwaga (na podstawie mojego zrozumienia i eksperymentowania, ale nie z udokumentowanego źródła), stwierdzenie

= = jeśli obiekty, do których odnoszą się zmienne, są równe

Z powyższych odpowiedzi należy odczytać jako

= = jeśli obiekty, do których odnoszą się zmienne, są równe i obiekty należące do tego samego typu / klasy

. Doszedłem do tego wniosku na podstawie poniższego test:

list1 = [1,2,3,4]
tuple1 = (1,2,3,4)

print(list1)
print(tuple1)
print(id(list1))
print(id(tuple1))

print(list1 == tuple1)
print(list1 is tuple1)

Tutaj zawartość listy i krotki są takie same, ale Typ / Klasa są inne.

 2
Author: Sandeep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-07 08:05:20

Różnica w Pythonie pomiędzy is I equals (==)

Operator is może wydawać się taki sam jak operator równości, ale nie są takie same.

Is sprawdza, czy obie zmienne wskazują na ten sam obiekt, podczas gdy znak = = sprawdza, czy wartości obu zmiennych są takie same.

Więc jeśli operator is zwraca True to równość jest definitywna Prawda, ale odwrotnie może być, ale nie musi być prawdą.

Oto przykład do zademonstrowania podobieństwo i różnica.

>>> a = b = [1,2,3]
>>> c = [1,2,3]
>>> a == b
True
>>> a == c
True
>>> a is b
True
>>> a is c
False
>>> a = [1,2,3]
>>> b = [1,2]
>>> a == b
False
>>> a is b
False
>>> del a[2]
>>> a == b
True
>>> a is b
False
Tip: Avoid using is operator for immutable types such as strings and numbers, the result is unpredictable.
 2
Author: Projesh Bhoumik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-08 12:30:33

Jako, że inni ludzie w tym poście odpowiadają na pytanie szczegółowo różnica między == i is do porównywania obiektów lub zmiennych, chciałbym podkreślić głównie porównanie między is i == dla ciągów , które mogą dawać różne wyniki i zachęcam programistów do uważnego ich używania.

Dla porównania łańcuchów, upewnij się, że używasz == zamiast is:

str = 'hello'
if (str is 'hello'):
    print ('str is hello')
if (str == 'hello'):
    print ('str == hello')

Out:

str is hello
str == hello

Ale W poniższym przykładzie == i is otrzymają różne wyniki:

str2 = 'hello sam'
    if (str2 is 'hello sam'):
        print ('str2 is hello sam')
    if (str2 == 'hello sam'):
        print ('str2 == hello sam')

Out:

str2 == hello sam

Wnioski i analizy:

Użyj is ostrożnie, aby porównać między łańcuchami. Ponieważ is do porównywania obiektów i ponieważ w Pythonie 3+ każda zmienna, taka jak string, interpretuje jako obiekt, zobaczmy, co się stało w powyższych akapitach.

W Pythonie jest id funkcja, która pokazuje unikalną stałą obiektu podczas jego życia. Ten identyfikator jest używany w back-endzie Pythona interpreter porównujący dwa obiekty za pomocą słowa kluczowego is.

str = 'hello'
id('hello')
> 140039832615152
id(str)
> 140039832615152

Ale

str2 = 'hello sam'
id('hello sam')
> 140039832615536
id(str2)
> 140039832615792
 1
Author: imanzabet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-21 01:40:51