diff --git a/electrum/exchange_rate.py b/electrum/exchange_rate.py index 5cae92fcb..ed7effaf5 100644 --- a/electrum/exchange_rate.py +++ b/electrum/exchange_rate.py @@ -17,7 +17,8 @@ from . import util from .bitcoin import COIN from .i18n import _ from .util import (ThreadJob, make_dir, log_exceptions, OldTaskGroup, - make_aiohttp_session, resource_path, EventListener, event_listener, to_decimal) + make_aiohttp_session, resource_path, EventListener, event_listener, to_decimal, + timestamp_to_datetime) from .util import NetworkRetryManager from .network import Network from .simple_config import SimpleConfig @@ -306,7 +307,7 @@ class CoinCap(ExchangeBase): # (and history starts on 2017-03-23) history = await self.get_json('api.coincap.io', '/v2/assets/bitcoin/history?interval=d1&limit=2000') - return dict([(datetime.utcfromtimestamp(h['time']/1000).strftime('%Y-%m-%d'), str(h['priceUsd'])) + return dict([(timestamp_to_datetime(h['time']/1000, utc=True).strftime('%Y-%m-%d'), str(h['priceUsd'])) for h in history['data']]) @@ -354,7 +355,7 @@ class CoinGecko(ExchangeBase): history = await self.get_json('api.coingecko.com', '/api/v3/coins/bitcoin/market_chart?vs_currency=%s&days=max' % ccy) - return dict([(datetime.utcfromtimestamp(h[0]/1000).strftime('%Y-%m-%d'), str(h[1])) + return dict([(timestamp_to_datetime(h[0]/1000, utc=True).strftime('%Y-%m-%d'), str(h[1])) for h in history['prices']]) @@ -371,7 +372,7 @@ class Bit2C(ExchangeBase): history = await self.get_json('bit2c.co.il', '/Exchanges/BtcNis/KLines?resolution=1D&from=1357034400&to=%s' % int(time.time())) - return dict([(datetime.utcfromtimestamp(h[0]).strftime('%Y-%m-%d'), str(h[6])) + return dict([(timestamp_to_datetime(h[0], utc=True).strftime('%Y-%m-%d'), str(h[6])) for h in history]) diff --git a/electrum/logging.py b/electrum/logging.py index 66be956a5..f0c137ba3 100644 --- a/electrum/logging.py +++ b/electrum/logging.py @@ -134,7 +134,7 @@ def _configure_file_logging(log_directory: pathlib.Path, *, num_files_keep: int) _delete_old_logs(log_directory, num_files_keep=num_files_keep) - timestamp = datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ") + timestamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%dT%H%M%SZ") PID = os.getpid() _logfile_path = log_directory / f"electrum_log_{timestamp}_{PID}.log" diff --git a/electrum/util.py b/electrum/util.py index 80ec65fc7..740177fbe 100644 --- a/electrum/util.py +++ b/electrum/util.py @@ -26,7 +26,7 @@ import os, sys, re, json from collections import defaultdict, OrderedDict from typing import (NamedTuple, Union, TYPE_CHECKING, Tuple, Optional, Callable, Any, Sequence, Dict, Generic, TypeVar, List, Iterable, Set, Awaitable) -from datetime import datetime +from datetime import datetime, timezone import decimal from decimal import Decimal import traceback @@ -808,10 +808,13 @@ def quantize_feerate(fee) -> Union[None, Decimal, int]: return Decimal(fee).quantize(_feerate_quanta, rounding=decimal.ROUND_HALF_DOWN) -def timestamp_to_datetime(timestamp: Union[int, float, None]) -> Optional[datetime]: +def timestamp_to_datetime(timestamp: Union[int, float, None], *, utc: bool = False) -> Optional[datetime]: if timestamp is None: return None - return datetime.fromtimestamp(timestamp) + tz = None + if utc: + tz = timezone.utc + return datetime.fromtimestamp(timestamp, tz=tz) def format_time(timestamp: Union[int, float, None]) -> str: diff --git a/electrum/x509.py b/electrum/x509.py index 68cf92b94..424793e5c 100644 --- a/electrum/x509.py +++ b/electrum/x509.py @@ -25,10 +25,9 @@ import hashlib import time -from datetime import datetime from . import util -from .util import profiler +from .util import profiler, timestamp_to_datetime from .logging import get_logger @@ -307,7 +306,7 @@ class X509(object): if self.notBefore > now: raise CertificateError('Certificate has not entered its valid date range. (%s)' % self.get_common_name()) if self.notAfter <= now: - dt = datetime.utcfromtimestamp(time.mktime(self.notAfter)) + dt = timestamp_to_datetime(time.mktime(self.notAfter), utc=True) raise CertificateError(f'Certificate ({self.get_common_name()}) has expired (at {dt} UTC).') def getFingerprint(self):