第三章:数字日期和时间

文章目录

第一节:数字

数字的四舍五入

使用 round(value, ndigits) 进行四舍五入

例:

#四舍五入1.23,保留1位小数
print(round(1.23, 1))      # 1.2

#四舍五入1.27,保留1位小数
print(round(1.27, 1))      # 1.3

#四舍五入-1.27,保留1位小数
print(round(-1.27, 1))     # -1,3

#四舍五入1.25361,保留3位小数
print(round(1.25361, 3))   # 1.254

#刚好在两个边界的中间的时候, round 函数返回离它最近的偶数
print(round(1.5))   # 2
print(round(2.5))   # 2

round() 函数的 ndigits 参数可以是负数,这种情况下,舍入运算会作用在
十位、百位、千位等上面

例:

a = 19981231
print(round(a,-1))   # 19981230
print(round(a,-2))   # 19981200
print(round(a,-3))   # 19981000

精确的浮点数运算

使用 decimal.Decimal() 精确浮点数

由于浮点数的一个普遍问题是它们并不能精确的表示十进制数。并且,即使是最简单的
数学运算也会产生小的误差,但有些业务必须分毫不差,需要此方法

例:

from decimal import Decimal

a = Decimal('4.2')
b = Decimal('2.1')

print(a + b)     # 6.3
print((a + b) == Decimal('6.3'))   # True

数字的格式化输出

使用 format() 进行数字格式化

格式化输出单个数字的时候,可以使用此方法

例:

a = 1234.567899

#2精度
print(format(a,'0.2f'))       # '1234.57'
#10宽1精右对齐
print(format(a, '>10.1f'))    # '    1234.6'
#10宽1精左对齐
print(format(a, '<10.1f'))    # '1234.6    '
#10宽1精中心对齐
print(format(a, '^10.1f'))    # '  1234.6  '
#包含千号分隔符
print(format(a, ','))         # '1,234.56789'
print(format(a, '0,.1f'))     # '1,234.6'
#指数记法
print(format(x, 'e'))         # '1.234568e+03'

二、八、十六进制转换

十进制转其他进制*
使用 bin() ,oct() 或 hex() +format() 函数转换

例:

x = 1234

#转为二进制
print(bin(x))     # '0b10011010010'
#转为八进制
print(oct(x))     # '0o2322'
#转为十六进制
print(hex(x))     # '0x4d2'
使用format() 转换

使用format(),不但能转化进制,还能消除上面方法的 0b , 0o 或者 0x 的前缀

例:

x = 1234

#十进制转为二进制
print(format(x,'b'))  # 10011010010
#十进制转为八进制
print(format(x,'o'))  # 2322
#十进制转为十进制
print(format(x,'x'))  # 4d2

#整数是有符号的,所以如果你在处理负数的话,输出结果会包含一个负号
其他进制转十进制
使用 int() 进行转换

例:

#二进制转十进制
print(int('10011010010', 2))   # 1234
#八进制转十进制
print(int('2322',8))           # 1234
#十六进制转十进制
print(int('4d2', 16))          # 1234

字节与整数的转换

整数转为字节字符串
使用 int.to_bytes() 进行转换

例:

x = 94522842520747284487117727783387188

#转换,并指定字节数和字节顺序
print(x.to_bytes(16, 'big'))
# b'\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004'

#转换,并指定字节数和字节顺序
print(x.to_bytes(16, 'little'))
# b'4\x00#\x00\x01\xef\xcd\x00\xab\x90

字节顺序是什么?
字节顺序规则 (little 或 big) 仅仅指定了构建整数时的字节的低位高位排列方式。比如下面 16 进制数的表示中可以很容易的看出来:

x = 0x01020304
print(x.to_bytes(4, 'big'))      # b'\x01\x02\x03\x04'
print(x.to_bytes(4, 'little'))   # b'\x04\x03\x02\x01'
字节字符串转为整数
使用 int.from bytes() 进行转换

把一个拥有 128 位长的 16 个元素的字节字符串解析为整数

例:

data = b'\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004'

print(len(data))   # 16

#转换并指定字节顺序为little
print(int.from_bytes(data, 'little')) # 69120565665751139577663547927094891008

#转换并指定字节顺序为big
print(int.from_bytes(data, 'big'))    # 94522842520747284487117727783387188
使用 struct.unpack() 进行转换

struct 模块也能解压字节。不过利用 struct 模块来解压对于整数的大小是有限制的只能应付小的整数数。此方法,需要解压多个字节串并将结果合并为

例:

data = b'\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004'

import struct

A ,B = struct.unpack('>QQ', data)
print((A << 64) + B)        # 94522842520747284487117727783387188>

复数的运算

复数的定义
使用【j】和【complex(real, imag)】进行定义

例:

a = complex(3, 5)
b = 3 - 5j
print(a)       # (3+5j)
print(b)       # (3-5j)
获取复数的实部、虚部、共轭复数

例:

a = complex(3, 5)     # 即(3+5j)

#复数的实部
print(a.real)         # 3.0
#复数的虚部
print(a.imag)         # 5.0
#复数的共轭复数
print(a.conjugate())  # (3+5j)
复数的数学运算
直接用运算符进行运算

例:

a = complex(3, 5)
b = 3 - 5j

print(a + b)   # (6+0j)
print(a - b)   # 10j
print(a * b)   # (34+0j)
print(a / b)   # (-0.4705882352941177+0.8823529411764706j)
print(abs(a))  # 5.830951894845301
print(abs(b))  # 5.830951894845301
使用 numpy模块进行运算

Python 中大部分与数学相关的模块都能处理复数。比如如果你使用 numpy ,可以
很容易的构造一个复数数组并在这个数组上执行各种操作

例:

a = complex(3, 5)
b = 3 - 5j

import numpy as np
print(np.array([a]) + np.array([b]))  # [6.+0.j]
print(np.array([a]) - np.array([b]))  # [0.+10.j]

c = np.array([3+5j,3-5j,2-3j])
print(c+3)                            # [6.+5.j 6.-5.j 5.-3.j]
求复数的正弦、余弦、平方根
使用 cmath 模块求值

例:

a = complex(3, 5)

import cmath

#复数的正弦
print(cmath.sin(a))   # (10.472508533940392-73.46062169567367j)
#复数的余弦
print(cmath.cos(a))   # (-73.46729221264526-10.471557674805572j)
#复数的平方根
print(cmath.exp(a))   # (5.697507299833739-19.26050892528742j)

无穷大与 NaN

使用 float() 创建无穷与NaN

例:

a = float('inf')
b = float('-inf')
c = float('NaN')

print(a,',type(a)=',type(a))   # inf ,type(a)= <class 'float'>
print(b,',type(b)=',type(b))   # -inf ,type(b)= <class 'float'>
print(c,',type(c)=',type(c))   # nan ,type(c)= <class 'float'>
使用 math.isinf() 和 math.isnan()测试无穷与NaN

例:

a = float('inf')
c = float('NaN')

import math

print(math.isinf(a))  # True
print(math.isnan(c))  # True
无穷与NaN有意思的操作

例:

a = float('inf')
b = float('-inf')
c = float('NaN')
d = float('NaN')

#无穷 / 无穷 =  非数字
print(a / a)               # nan
#正无穷 + 负无穷 = 非数字
print(a + b)               # nan
#无穷 + 非数字 = 非数字
print(a + c)               # nan
# 非数字+ 数字 = 非数字
print(c + 5)               # nan


#NaN永远不相等
print(c==d)                # False
print(c is d)              # False

分数运算

使用 fractions.Fraction() 进行分数相加减

正常的分数运算,得到的往入是一个符点数,而不是分数,当结果想等于分数时,可用此法

例:

#正常计算
c = 5/4
d = 7/16
print(c+d)            # 1.6875

#以下运用fractions.Fraction()计算

from fractions import Fraction

a = Fraction(5, 4)
b = Fraction(7, 16)
print(a)              # 5/4
print(a+b)            # 27/16
print(a*b)            # 35/64
使用 numerator()获得分子与分母

例:

from fractions import Fraction

a = Fraction(5, 4)
b = Fraction(7, 16)
F = a*b
#分子
print(F.numerator)    # 35
#分母
print(F.denominator)  # 64
使用 float(),将分数转为小数(浮点数)

例:

from fractions import Fraction

a = Fraction(5, 4)
b = Fraction(7, 16)
F = a*b

print(float(F))       # 0.546875
使用.as_integer_ratio()参数将小数(浮点数)转分数

例:

x = 3.75
y = Fraction(*x.as_integer_ratio())
print(y)              # 15/4

数组运算

使用 Numpy模块进行运算

NumPy 的一个主要特征是它会给 Python 提供一个数组对象,相比Python 列表而更适合用来做数学运算。下面展示标准列表对象和 NumPy 数组对象之间的差别:

例:

# python 列表
x = [1, 2, 3, 4]
y = [5, 6, 7, 8]
print(x * 2)         # [1, 2, 3, 4, 1, 2, 3, 4]
print(x + y)         # [1, 2, 3, 4, 5, 6, 7, 8]
# print(x + 10)      # 报错


#以下使用 Numpy
import numpy as np

ax = np.array([1, 2, 3, 4])
ay = np.array([5, 6, 7, 8])
print(ax * 2)        # array([2 4 6 8])
print(ax + ay)       # array([6, 8, 10, 12]),注意两数组元素个数需相等
print(ax + 10)       # array([11, 12, 13, 14])
对整个数组中所有元素同时执行数学运算

对整个数组中所有元素同时执行数学运算可以使得作用在整个数组上的函数运算简
单而又快速。

例:计算多项式的值

import numpy as np

ax = np.array([1, 2, 3, 4])
def f(x):
    return 3*x**2 - 2*x + 7

print(f(ax),type(f(ax)))  #array([ 8, 15, 28, 47])
数组对象的通用函数

Numpy 为数组操作提供了大量的通用函数,这些函数可以作为 math 模块中类似函数的替代。

例:

import numpy as np

ax = np.array([1, 2, 3, 4])

print(np.sqrt(ax))  #array([ 1. , 1.41421356, 1.73205081, 2. ])
print(np.cos(ax))   #array([ 0.54030231, -0.41614684, -0.9899925 , -0.65364362])

使用这些通用函数要比循环数组并使用 math 模块中的函数执行计算要快的多。因此,只要有可能的话尽量选择 NumPy 的数组方案。

构造一个 10,000*10,000 的浮点数二维网格

例:

import numpy as np

g = np.zeros(shape=(10000,10000), dtype=float)
print(g)
'''
	[[0. 0. 0. ... 0. 0. 0.]
	 [0. 0. 0. ... 0. 0. 0.]
	 [0. 0. 0. ... 0. 0. 0.]
	 ...
	 [0. 0. 0. ... 0. 0. 0.]
	 [0. 0. 0. ... 0. 0. 0.]
	 [0. 0. 0. ... 0. 0. 0.]]'''
print(g + 10)
'''
	[[10. 10. 10. ... 10. 10. 10.]
	 [10. 10. 10. ... 10. 10. 10.]
	 [10. 10. 10. ... 10. 10. 10.]
	 ...
	 [10. 10. 10. ... 10. 10. 10.]
	 [10. 10. 10. ... 10. 10. 10.]
	 [10. 10. 10. ... 10. 10. 10.]]'''

print(np.sin(g+5))
'''
	[[-0.95892427 -0.95892427 -0.95892427 ... -0.95892427 -0.95892427
	  -0.95892427]
	 [-0.95892427 -0.95892427 -0.95892427 ... -0.95892427 -0.95892427
	  -0.95892427]
	 [-0.95892427 -0.95892427 -0.95892427 ... -0.95892427 -0.95892427
	  -0.95892427]
	 ...
	 [-0.95892427 -0.95892427 -0.95892427 ... -0.95892427 -0.95892427
	  -0.95892427]
	 [-0.95892427 -0.95892427 -0.95892427 ... -0.95892427 -0.95892427
	  -0.95892427]
	 [-0.95892427 -0.95892427 -0.95892427 ... -0.95892427 -0.95892427
	  -0.95892427]]'''
多维数组列表的索引功能

例:

import numpy as np

#数组的索引
a = np.array([[1, 2, 3, 4], 
	          [5, 6, 7, 8], 
	          [9, 10, 11, 12]])
print(a)
'''
    array([[ 1, 2, 3, 4],
           [ 5, 6, 7, 8],
           [ 9, 10, 11, 12]])   
'''

print(a[1])          # array([5, 6, 7, 8])
print(a[:,1])        # array([ 2, 6, 10])
print(a[1:3, 1:3])   # array([[ 6, 7],[10, 11]])

#选择一个区间并改变它
a[1:3, 1:3] += 10
print(a)
'''
    array([[ 1, 2, 3, 4],
           [ 5, 16, 17, 8],
           [ 9, 20, 21, 12]])  
'''

#在所有行的操作上按顺序加上[100, 101, 102, 103]
print(a + [100, 101, 102, 103])
'''
    array([[101, 103, 105, 107],
          [105, 117, 119, 111],
          [109, 121, 123, 115]])   
'''
print(a)
'''
    array([[ 1, 2, 3, 4],
           [ 5, 16, 17, 8],
           [ 9, 20, 21, 12]])   
'''

#按条件对数组赋值
print(np.where(a < 10, a, 10))
'''
    array([[ 1, 2, 3, 4],
           [ 5, 10, 10, 8],
           [ 9, 10, 10, 10]])   
'''

矩阵与线性代数运算

使用 np.matrix()

Numpy 库有一个矩阵对象 np.matrix(),可以用来解决执行矩阵和线性代数运算问题,比如矩阵乘法、寻找行列式、求解线性方程组等等

例:

import numpy as np

#矩阵
m = np.matrix([[1,-2,3],
               [0,4,5],
               [7,8,-9]])

# 转置矩阵(列变行,行变列)
print(m.T)
'''
    matrix([[ 1, 0, 7],
            [-2, 4, 8],
            [ 3, 5, -9]])
'''

# 逆矩阵(又叫反矩阵)
print(m.I)
'''
    matrix([[ 0.33043478, -0.02608696, 0.09565217],
            [-0.15217391, 0.13043478, 0.02173913],
            [ 0.12173913 0.09565217 -0.0173913 ]])     
'''

# 增加一个矢量,然后相乘
v = np.matrix([[2],[3],[4]])
print(v)
'''
    matrix([[2],
            [3],
            [4]])   
'''

print(m * v)
'''
    matrix([[ 8],
            [32],
            [ 2]])   
'''

随机选择

序列中随机抽取若干元素
使用 random.choice() / random.choices() 随机抽取

例:

import random

list = [1,2,3,4,5,6,7,8,9]

print(random.choice(list))    # 6
print(random.choices(list))   # [2]
print(random.choice(list))    # 7
print(random.choices(list))   # [8]
使用 random.sample() 提取N 个不同元素的样本

例:

import random

list = [1,2,3,4,5,6,7,8,9]

print(random.sample(list,2))   # [7, 1]
print(random.sample(list,5))   # [5, 3, 7, 9, 4]
打乱序列中元素的顺序
使用 random.shuffle() 打乱

例:

import random

list = [1,2,3,4,5,6,7,8,9]

random.shuffle(list)
print(list)      # [1, 3, 2, 9, 6, 4, 7, 8, 5]
生成随机整数
使用 random.randint() 生成

例:

import random

#此含数含头也含尾
print(random.randint(0,10))   # 0
print(random.randint(11,15))  # 15
随机生成 0 到 1 范围内的浮点数
使用 random.random() 生成

例:

import random

#此含数lfnh不需要输入数字范围
print(random.random())    # 0.6241793984826816
print(random.random())    # 0.31916117699998503
print(random.random())    # 0.6904611405280672
获取 N 位随机位 (二进制) 的整数
使用 random.getrandbits() 获取

例:

import random

# 此方法返回具有k随机位的一个Python整数
print(random.getrandbits(5))  # 15

第二节:时间与日期

基本的日期与时间转换

datetime 模块可以执行不同时间单位的转换和计算

使用 datetime.timedelta() 获得一个时间段

例:

from datetime import timedelta

a = timedelta(days=2, hours=6)
b = timedelta(hours=4.5)
# a 的实例
print(a)                # 2 days, 6:00:00
# b的实例
print(b)                # 4:30:00

c = a + b

print(c)                # 2 days, 10:30:00
print(c.days)           # 2
print(c.seconds)        # 37800
#小时 = 秒数/3600秒
print(c.seconds/3600)   # 10.5
#总小时=总秒数/3600秒
print(c.total_seconds()/3600) # 58.5

时间和日期操作

使用 datetime() +标准的数学运算

例:

from datetime import datetime, timedelta

# 指定日期
a = datetime(2012, 9, 23)
print(a)                       # 2012-09-23 00:00:00

# 指定日期+ 一段时间
print(a + timedelta(days=10))  # 2012-10-03 00:00:00

# 指定日期 - 指定日期
b = datetime(2012, 12, 21)
d = b - a
print(d)                       # 89 days, 0:00:00
print(d.days)                  # 89

#现在时间
now = datetime.today()
print(now)                     # 2018-09-09 16:01:22.172384

#现在时间 + 一段时间
print(now + timedelta(minutes=10)) # 2018-09-09 16:11:22.172384
使用 dateutil.relativedelta() 进行时间操作

对大多数基本的日期和时间处理问题, datetime 模块以及足够了,但如需要执行更加复杂的日期操作,比如处理时区,模糊时间范围,节假日计算等等,可以考虑此方法

例:

from datetime import datetime, timedelta

a = datetime(2018,9,22)

# datetime() + 模糊时间段
print(a + timedelta(months=1))   # 报错


'''使用 relativedelta()'''
from dateutil.relativedelta import relativedelta

# datetime() + 模糊时间段
print(a + relativedelta(months=1))  # 2018-10-22 00:00:00

# 指定日期 - 指定日期
b = datetime(2018, 12, 21)
d = b - a
print(d)    #90 days, 0:00:00

d = relativedelta(b,a)
print(d)    #relativedelta(months=+2, days=+29)
print(d.months) # 2
print(d.days)   # 29

查找星期中某一天最后出现的日期

使用 dateutil 模块中的 relativedelta() 查找

例:找查最后一个星期五

from datetime import datetime
from dateutil.relativedelta import relativedelta
from dateutil.rrule import *

# 现在的日期与时间
d = datetime.now()
print(d)   # 2018-09-09 17:13:35.301246

# 下周五的日期
print(d + relativedelta(weekday=FR))  # 2018-09-14 17:15:01.

# 最后一个星期五的日期
print(d + relativedelta(weekday=FR(-1))) #2018-09-07 17:17:40.549931
使用 datetime 模块查找

算法原理:先将开始日期和目标日期映射到星期数组的位置上 (星期一索引为 0),然后通过模运算计算出目标日期要经过多少天才能到达开始日期。然后用开始日期减去那个时间差即得到结果日期。

例:

from datetime import datetime, timedelta

weekdays = ['Monday', 'Tuesday', 'Wednesday',
            'Thursday','Friday', 'Saturday', 'Sunday']

def get_previous_byday(dayname, start_date=None):
    if start_date is None:
        start_date = datetime.today()
    day_num = start_date.weekday()
    day_num_target = weekdays.index(dayname)
    days_ago = (7 + day_num - day_num_target) % 7
    if days_ago == 0:
        days_ago = 7
    target_date = start_date - timedelta(days=days_ago)
    return target_date

print(get_previous_byday('Friday'))  # 2018-09-07 17:17:40.549931

计算当前月份的日期范围

使用datetime模块方法

例:

from datetime import datetime, date, timedelta
import calendar

#定义一个函数,返回开始日期和结束日期
def totalDays(start_date=None):
    #开始日期,如果没有开始日期则定义本月首日
    if start_date is None:
        start_date = date.today().replace(day=1)
        print('开始日期是:',start_date)   # 2018-09-09

    # 本月1号的星期索引和本月天数
    index, days_in_month = calendar.monthrange(start_date.year, start_date.month)
    # print(index, days_in_month)           # 5 30

    #一个月后的日期
    end_date = start_date + timedelta(days=days_in_month)
    print('一个月后的日期是:',end_date)   # 2018-10-01
    
    return (start_date, end_date)



#定义一个时间段=1天
a_day = timedelta(days=1)

#使用函数,得到开始日跟结束日
first_day, last_day = totalDays()

# 循环判断
#如是开始日< 结束日,打印开始日,并让开始日+ 1天
while first_day < last_day:
    print(first_day)
    first_day += a_day
'''
	2018-09-01
	2018-09-02
	2018-09-03
	2018-09-04
	...
	2018-09-30
'''

tips:
replace() 方法一个好处就是它会创建和你开始传入对象类型相同的对象。所以,如果输入参是一个 date 实例,那么结果也是一个 date 实例。同样的,如果输入是一个 datetime实例,那么你得到的就是一个 datetime 实例

使用生成器方法

例:

# 定义一个函数,获得生成器列表
def date_range(start, stop, step):
    while start < stop:
        yield start
        start += step

from datetime import datetime, timedelta

# 遍历列表
for d in date_range(datetime(2018,9,1),datetime(2018,10,1),timedelta(days=1)):
    print(d)

字符串转换为日期

使用 datetime.strptime() 进行转换

例:

from datetime import datetime

# 时间字符串
mystring = '2018-09-01'

# 将时间字符串转化为时间,并定义格式
a = datetime.strptime(mystring, '%Y-%m-%d')
print(a)         # 2018-09-01 00:00:00

# 现在时间
b = datetime.now()
print(b)         # 2018-09-10 01:41:55.979311

#执行时间操作
c = b - a
print(c)         # 9 days, 1:38:52.124994

strptime() 的性能要比你想象中的差很多,因为它是使用纯 Python 实现,并且必须处理所有的系统本地设置。如果你要在代码中需要解析大量的日期并且已经知道了日期字符串的确切格式,可以自己实现一套解析方案来获取更好的性能。比如:

例:

from datetime import datetime

#定义一个方法,返回日期整数
def turn_to_time(s):
    #把字符串炸开
    year_s, mon_s, day_s = s.split('-')
    #返回日期
    return datetime(int(year_s), int(mon_s), int(day_s))

mystring = '2018-09-01'
print(turn_to_time(mystring))  # 2018-09-01 00:00:00

时间转字符串

时间也可以转化为自符串,并且可以按自定义的格式去处理

使用 datetime.strftime() 进行转换

例:

from datetime import datetime

# 现在时间
b = datetime.now()
print(b)      # 2018-09-10 01:41:55.979311

# 时间转为字符串,并设定想要的时间格式
B = datetime.strftime(b, '%A %B %d, %Y')
print(B)      # Monday September 10, 2018

配合时区的日期操作

对几乎所有涉及到时区的问题,你都应该使用 pytz 模块。这个包提供了 Olson 时区数据库,它是时区信息的事实上的标准,pytz 模块一个主要用途是将 datetime 库创建的简单日期对象本地化

例:你有一个安排在 2012 年 12 月 21 日早上 9:30 的电话会议,地点在芝加哥。而你的朋友在印度的班加罗尔,那么他应该在当地时间几点参加这个会议呢?

from datetime import datetime
from pytz import timezone

#现在时间
d = datetime(2018, 12, 21, 9, 30, 0)
print(d)   # 2018-12-21 09:30:00

#芝加哥的日期
central = timezone('US/Central')
loc_d = central.localize(d)
print(loc_d)   # 2018-12-21 09:30:00-06:00

#转换到班加罗尔时间
bang_d = loc_d.astimezone(timezone('Asia/Kolkata'))
print(bang_d)  #2 018-12-21 21:00:00+05:30

UTC 时间

处理本地化日期的通常的策略先将所有日期转换为 UTC 时间,并用它来执行所有的中间存储和操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值