-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhaircut.py
102 lines (93 loc) · 3.61 KB
/
haircut.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# coding=utf-8
#
# A script to calculate some basic stats on Grant Hutchinson’s haircuts.
# See: https://splorp.com/about/haircut/
#
# Requires Python 3
# https://www.python.org/downloads/
# Requires Beautiful Soup 4
# https://www.crummy.com/software/BeautifulSoup/
#
# Sample output:
#
# Number of haircuts recorded: 140 (Since October 10, 1998)
# Shortest time between haircuts: 9 days (July 21, 2016 to July 30, 2016)
# Longest time between haircuts: 138 days (November 28, 2022 to April 15, 2023)
# Median time between haircuts: 69.0 days
# Average time between haircuts: 68.8 days
# Average time between last six haircuts: 50.8 days
# Your last haircut was yesterday.
# You probably should get another haircut in about 49 days. (February 05, 2025)
import datetime
import urllib.request
import os, ssl
if (not os.environ.get('PYTHONHTTPSVERIFY', '') and
getattr(ssl, '_create_unverified_context', None)):
ssl._create_default_https_context = ssl._create_unverified_context
from bs4 import BeautifulSoup
calendar = 'january february march april may june july august september october november december'.split()
url = 'https://splorp.com/about/haircut'
hdr = { 'User-agent' : 'Mozilla 5.10' }
page = urllib.request.Request(url, headers=hdr)
response = urllib.request.urlopen(page)
def fetch_dates():
soup = BeautifulSoup(response, 'html.parser')
return [span.string for span in soup.findAll('span', {'class': 'dtstart'})]
def get_dates():
dates = []
for d in fetch_dates():
day, month, year = d.lower().split()
date = datetime.date(int(year), int(calendar.index(month))+1, int(day))
dates.append(date)
dates.sort()
return dates
def get_deltas(dates):
deltas = []
mx = None
mx_delta = None
mn = None
mn_delta = None
for idx in range(0, len(dates)):
if idx > 0:
days = (dates[idx] - dates[idx-1]).days
if mx_delta is None or mx_delta < days:
mx_delta = days
mx = (dates[idx-1], dates[idx])
if mn_delta is None or mn_delta > days:
mn_delta = days
mn = (dates[idx-1], dates[idx])
deltas.append(days)
return mn, mx, deltas
def median(data):
quotient, remainder = divmod(len(data), 2)
if remainder:
return sorted(data)[quotient]
return sum(sorted(data)[quotient - 1:quotient + 1]) / 2.
if __name__ == '__main__':
str = '%B %d, %Y'
dates = get_dates()
mn, mx, deltas = get_deltas(dates)
mdn = median(deltas)
avg = (sum(deltas) / len(deltas))
avgm = (sum(deltas[-6:]) / 6)
today = datetime.date.today()
last = dates[-1]
next = (last + datetime.timedelta(days=avgm))
print("")
print(f"Number of haircuts recorded: {len(dates)} (Since {dates[0].strftime('%B %d, %Y')})")
print(f"Shortest time between haircuts: {(mn[1]-mn[0]).days} days ({mn[0].strftime(str)} to {mn[1].strftime(str)})")
print(f"Longest time between haircuts: {(mx[1]-mx[0]).days} days ({mx[0].strftime(str)} to {mx[1].strftime(str)})")
print(f"Median time between haircuts: {mdn:.1f} days")
print(f"Average time between haircuts: {avg:.1f} days")
print(f"Average time between last six haircuts: {avgm:.1f} days")
if (today-last).days == 0:
print("You got your haircut today. Awesome.")
if (today-last).days == 1:
print("Your last haircut was yesterday.")
if (today-last).days > 1:
print(f"Your last haircut was {(today-last).days} days ago. ({last.strftime(str)})")
if (next-datetime.date.today()).days <= -1:
print(f"You probably should’ve had a haircut {abs((next-datetime.date.today()).days)} days ago. ({next.strftime(str)})")
if (next-datetime.date.today()).days >= 1:
print(f"You probably should get another haircut in about {abs((next-datetime.date.today()).days)} days. ({next.strftime(str)})")
print("")