Преобразование взад и вперед от UTC дает разные результаты [дублировать]

== тесты для ссылочного равенства (независимо от того, являются ли они одним и тем же объектом).

.equals() тесты для равенства значений (независимо от того, являются ли они логически «равными»).

Objects.equals () проверяет наличие null перед вызовом .equals(), поэтому вам не нужно (доступно с JDK7, также доступным в Guava ).

String.contentEquals () сравнивает содержимое String с содержимым любого CharSequence (доступно с Java 1.5).

Следовательно, если вы хотите проверить, имеет ли две строки одно и то же значение, вы, вероятно, захотите использовать Objects.equals().

// These two have the same value
new String("test").equals("test") // --> true 

// ... but they are not the same object
new String("test") == "test" // --> false 

// ... neither are these
new String("test") == new String("test") // --> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" // --> true 

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

Вы почти всегда хотите использовать Objects.equals(). В редкой ситуации, когда вы знаете, что имеете дело с интернированными строками, вы можете использовать ==.

Из JLS 3.10. 5. Строковые литералы :

Кроме того, строковый литерал всегда ссылается на тот же экземпляр класса String. Это связано с тем, что строковые литералы, или, в более общем смысле, строки, которые являются значениями константных выражений ( §15.28 ), «интернированы», чтобы обмениваться уникальными экземплярами, используя метод String.intern.

. Подобные примеры также можно найти в JLS 3.10.5-1 .

40
задан Martijn Pieters 10 November 2017 в 14:14
поделиться

3 ответа

Для pytz часовых поясов используйте свой метод .localize(), чтобы превратить наивный объект datetime в один с часовым поясом:

start_date = local_tz.localize(start_date)

Для часовых поясов без перехода на летнее время .replace() метод для присоединения часового пояса к наивному объекту datetime должен также работать:

start_date = start_date.replace(tzinfo=local_tz)

См. локализованные времена и дату арифметики pytz для более подробной информации.

40
ответ дан Martijn Pieters 16 August 2018 в 00:50
поделиться
  • 1
    pytz docs говорят, что использование атрибута tzinfo напрямую не выполняется во многих часовых поясах. Вместо этого следует использовать tz.localize (). – jfs 3 October 2012 в 17:55
  • 2
    @ J.F.Sebastian за хороший пример того, насколько плохо он может потерпеть неудачу, см. stackoverflow.com/questions/11442183/… и обратите внимание, что это не имеет никакого отношения к DST. – Mark Ransom 3 October 2012 в 18:07
  • 3
    @ J.F.Sebastian: Интересно. Обновлен ответ. – Martijn Pieters♦ 3 October 2012 в 18:07
  • 4
    @MarkRansom: Я знаю. Например, pytz использует «Европа / Амстердам». – jfs 3 October 2012 в 18:18
  • 5
    Еще один WTF для python! – Kevin Parker 19 November 2014 в 20:23

Вы можете использовать local_tz.localize(naive_dt, is_dst=None), чтобы преобразовать наивный объект datetime в соответствующий момент времени.

from datetime import datetime
import pytz

local_tz = pytz.timezone('Asia/Tokyo')

start_date = local_tz.localize(datetime(2012, 9, 27), is_dst=None)
now_utc = datetime.utcnow().replace(tzinfo=pytz.utc)

print start_date > now_utc

is_dst=None принудительно .localize (), чтобы вызвать исключение, если заданное местное время неоднозначно.

14
ответ дан jfs 16 August 2018 в 00:50
поделиться

Если вы используете Django Rest Framework, вы можете переопределить класс DateTimeField, например:

class DateTimeFieldOverridden(serializers.DateTimeField):

def to_representation(self, value):
    local_tz = pytz.timezone(TIME_ZONE)
    value = local_tz.localize(value)
    return super(DateTimeFieldOverridden, self).to_representation(value)

И вы используете его как это в своем сериализаторе:

date_time = DateTimeFieldOverridden(format='%d-%b-%Y', read_only=True)

Надеюсь, что это помогает кому-то.

0
ответ дан Joseph Daudi 16 August 2018 в 00:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: