1.3. 数字日期时间

1.3.1. 数字的四舍五入

对于简单的舍入运算,使用内置的 round(value, ndigits) 函数即可

In [1]: round(1.5,0)
Out[1]: 2.0

In [2]: round(2.5,0)
Out[2]: 2.0

In [3]: round(2.51,0)
Out[3]: 3.0

In [4]: a = 1627731

In [5]: round(a,-2)
Out[5]: 1627700

1.3.2. 执行精确的浮点数运算

你可以使用 decimal 模块。

In [9]: a = 4.2

In [10]: b = 2.1

In [11]: a+b
Out[11]: 6.300000000000001

In [12]: (a + b) == 6.3
Out[12]: False

In [13]: from decimal import Decimal

In [14]:  a = Decimal('4.2')

In [15]: b = Decimal('2.1')

In [16]: (a + b) == Decimal('6.3')
Out[16]: True

In [17]: print(a+b)
6.3

1.3.3. 数字的格式化输出

In [18]: x = 1234.56789

In [19]: "{:.2f}".format(x)
Out[19]: '1234.57'

In [20]: "{:,.2f}".format(x)
Out[20]: '1,234.57'

In [21]: "{:,<10.2f}".format(x)
Out[21]: '1234.57,,,'

In [22]: "{:<10,.2f}".format(x)
Out[22]: '1,234.57  '

In [23]: "{:#<10,.2f}".format(x)
Out[23]: '1,234.57##'

1.3.4. 二八十六进制整数

为了将整数转换为二进制、八进制或十六进制的文本串, 可以分别使用 bin() , oct()hex()

In [24]:  x = 1234

In [25]: bin(x)
Out[25]: '0b10011010010'

In [26]: format(x,'b')
Out[26]: '10011010010'

1.3.5. 字节到大整数的打包与解包

将bytes解析为整数,使用 int.from_bytes()

1.3.6. 复数的数学运算

In [27]: a = complex(2, 4)

In [28]: a
Out[28]: (2+4j)

In [29]: a.real
Out[29]: 2.0

In [30]: a.imag
Out[30]: 4.0

In [31]: import cmath

In [33]: cmath.sqrt(-1)
Out[33]: 1j

1.3.7. 无穷大与NaN

Python并没有特殊的语法来表示这些特殊的浮点值,但是可以使用 float() 来创建它们。

为了测试这些值的存在,使用 math.isinf() 和 math.isnan() 函数。

In [34]: b = float('-inf')

In [35]: a=float('inf')

In [36]: a+b
Out[36]: nan

In [37]: c=float('nan')

In [38]: c
Out[38]: nan

In [40]: math.isinf(a)
Out[40]: True

1.3.8. 分数运算

fractions 模块可以被用来执行包含分数的数学运算。

In [42]: from fractions import Fraction

In [43]: a= Fraction(1,2)

In [44]: b= Fraction(1,3)

In [45]: a-b
Out[45]: Fraction(1, 6)

In [46]: a*b
Out[46]: Fraction(1, 6)

In [47]: float(a-b)
Out[47]: 0.16666666666666666

In [48]:  x = 3.75

In [49]: y = Fraction(*x.as_integer_ratio())

In [50]: y
Out[50]: Fraction(15, 4)

1.3.9. 大型数组运算

到数组的重量级运算操作,可以使用 NumPy 库。

比如: 执行矩阵和线性代数运算,比如矩阵乘法、寻找行列式、求解线性方程组。

1.3.10. 随机选择

In [51]: import random

In [52]: values = [1, 2, 3, 4, 5, 6]

In [53]: random.choice(values)
Out[53]: 3

In [55]: random.sample(values,3)
Out[55]: [1, 6, 2]

In [56]:  random.shuffle(values)

In [57]: values
Out[57]: [4, 3, 2, 6, 5, 1]

In [58]: random.randint(3,5)
Out[58]: 5

In [59]: random.randint(3,5)
Out[59]: 3

In [60]: random.randint(3,5)
Out[60]: 5

In [61]: random.random()
Out[61]: 0.8821204800599628

In [68]: bin(random.getrandbits(10))
Out[68]: '0b100111100'

1.3.11. 基本的日期与时间转换

对大多数基本的日期和时间处理问题, datetime 模块已经足够了。 如果你需要执行更加复杂的日期操作,比如处理时区,模糊时间范围,节假日计算等等, 可以考虑使用 dateutil模块

In [73]: a = timedelta(hours=1)

In [74]: b=timedelta(days=1,hours=25)

In [75]: a+b
Out[75]: datetime.timedelta(days=2, seconds=7200)


In [5]: a = datetime(2012, 9, 23)

In [6]: a + relativedelta(months=+1)
Out[6]: datetime.datetime(2012, 10, 23, 0, 0)

1.3.12. 计算最后一个周五的日期

In [7]:  from datetime import datetime

In [8]: from dateutil.relativedelta import relativedelta

In [9]: from dateutil.rrule import *

In [10]: print(datetime.now())
2024-02-03 20:42:04.969243

In [12]:  print(datetime.now() + relativedelta(weekday=FR))
2024-02-09 20:42:28.756677

In [13]:  print(datetime.now() + relativedelta(weekday=FR(-1)))
2024-02-02 20:42:41.233142

1.3.13. 计算当前月份的日期范围

from datetime import datetime,timedelta
import calendar

def get_start_and_end_of_month(dt=None):
    if dt is None:
        dt = datetime.today()
    start_dt = dt.replace(day=1,hour=0,minute=0,second=0,microsecond=0)
    end_dt = start_dt + timedelta(days=31)
    for diff in (31,30,29,28):
        if start_dt.month != end_dt.month:
            break
        end_dt = start_dt + timedelta(days=diff)
    return start_dt,end_dt

def get_start_and_end_of_month_v2(dt=None):
    if dt is None:
        dt = datetime.today()
    start_dt = dt.replace(day=1,hour=0,minute=0,second=0,microsecond=0)
    _, days_in_month = calendar.monthrange(start_dt.year, start_dt.month)
    end_dt = start_dt + timedelta(days=days_in_month)
    return start_dt,end_dt

def range_dt(start_dt,end_dt,timedelta=timedelta(days=1)):
    while start_dt < end_dt:
        yield start_dt
        start_dt += timedelta
   

start_dt,end_dt = get_start_and_end_of_month()
print(start_dt,end_dt)

start_dt,end_dt = get_start_and_end_of_month_v2()
print(start_dt,end_dt)

for dt in range_dt(start_dt,end_dt,timedelta(hours=6)):
    print(dt)

 









    

1.3.14. 字符串转换为日期

In [3]: from datetime import datetime

In [4]: text = '2012-09-20'

In [5]: y = datetime.strptime(text, '%Y-%m-%d')

Out[6]: datetime.datetime(2012, 9, 20, 0, 0)

1.3.15. 结合时区的日期操作

pytz 模块一个主要用途是将 datetime 库创建的简单日期对象本地化。 这个不推荐了, python已经内置了对zoneinfo的支持工作。

In [18]: from zoneinfo import ZoneInfo

In [19]: dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))

In [20]: dt
Out[20]: datetime.datetime(2020, 10, 31, 12, 0, tzinfo=zoneinfo.ZoneInfo(key='America/Los_Angeles'))

In [21]: shanghai = ZoneInfo('Asia/Shanghai')

In [22]: dt.astimezone(shanghai)
Out[22]: datetime.datetime(2020, 11, 1, 3, 0, tzinfo=zoneinfo.ZoneInfo(key='Asia/Shanghai'))