fa45d8aa5f
- health_checklist.json: 192.168.1.122→node122
- ocr_client.py: docstring IP→node122
- docs/market-data-requirements.md: IP→node122
- 所有API调用通过ProxyHandler({})绕过系统代理
Privoxy对node122:18003返回500,直连正常
362 lines
10 KiB
Python
362 lines
10 KiB
Python
"""The utils module contains shared functions and constants.
|
|
|
|
They are to be used internally.
|
|
"""
|
|
from functools import lru_cache
|
|
from enum import Enum
|
|
|
|
|
|
class _Days(Enum):
|
|
ROSH_HASHANA = 'Rosh Hashana'
|
|
YOM_KIPPUR = 'Yom Kippur'
|
|
SUCCOS = 'Succos'
|
|
SHMINI_ATZERES = 'Shmini Atzeres'
|
|
SIMCHAS_TORAH = 'Simchas Torah'
|
|
CHANUKA = 'Chanuka'
|
|
TU_BSHVAT = "Tu B'shvat"
|
|
PURIM_KATAN = 'Purim Katan'
|
|
PURIM = 'Purim'
|
|
SHUSHAN_PURIM = 'Shushan Purim'
|
|
PESACH = 'Pesach'
|
|
PESACH_SHENI = 'Pesach Sheni'
|
|
LAG_BAOMER = "Lag Ba'omer"
|
|
SHAVUOS = 'Shavuos'
|
|
TU_BAV = "Tu B'av"
|
|
TZOM_GEDALIA = 'Tzom Gedalia'
|
|
TENTH_OF_TEVES = '10 of Teves'
|
|
TAANIS_ESTHER = 'Taanis Esther'
|
|
SEVENTEENTH_OF_TAMUZ = '17 of Tamuz'
|
|
NINTH_OF_AV = '9 of Av'
|
|
|
|
|
|
_days_hebrew = {
|
|
_Days.ROSH_HASHANA: 'ראש השנה',
|
|
_Days.YOM_KIPPUR: 'יום כיפור',
|
|
_Days.SUCCOS: 'סוכות',
|
|
_Days.SHMINI_ATZERES: 'שמיני עצרת',
|
|
_Days.SIMCHAS_TORAH: 'שמחת תורה',
|
|
_Days.CHANUKA: 'חנוכה',
|
|
_Days.TU_BSHVAT: 'ט״ו בשבט',
|
|
_Days.PURIM_KATAN: 'פורים קטן',
|
|
_Days.PURIM: 'פורים',
|
|
_Days.SHUSHAN_PURIM: 'שושן פורים',
|
|
_Days.PESACH: 'פסח',
|
|
_Days.PESACH_SHENI: 'פסח שני',
|
|
_Days.LAG_BAOMER: 'ל״ג בעומר',
|
|
_Days.SHAVUOS: 'שבועות',
|
|
_Days.TU_BAV: 'ט״ו באב',
|
|
_Days.TZOM_GEDALIA: 'צום גדליה',
|
|
_Days.TENTH_OF_TEVES: 'י׳ בטבת',
|
|
_Days.TAANIS_ESTHER: 'תענית אסתר',
|
|
_Days.SEVENTEENTH_OF_TAMUZ: 'י״ז בתמוז',
|
|
_Days.NINTH_OF_AV: 'ט׳ באב'
|
|
}
|
|
|
|
|
|
MONTH_NAMES = [
|
|
'Nissan', 'Iyar', 'Sivan', 'Tammuz', 'Av', 'Elul', 'Tishrei', 'Cheshvan',
|
|
'Kislev', 'Teves', 'Shevat', 'Adar', 'Adar 1', 'Adar 2']
|
|
|
|
MONTH_NAMES_HEBREW = [
|
|
'ניסן', 'אייר', 'סיון', 'תמוז', 'אב', 'אלול', 'תשרי', 'חשון', 'כסלו',
|
|
'טבת', 'שבט', 'אדר', 'אדר א׳', 'אדר ב׳']
|
|
|
|
FAST_DAYS = [
|
|
'Tzom Gedalia', '10 of Teves', 'Taanis Esther', '17 of Tamuz', '9 of Av']
|
|
|
|
FAST_DAYS_HEBREW = [
|
|
'צום גדליה', 'י׳ בטבת', 'תענית אסתר', 'י״ז בתמוז', 'ט׳ באב']
|
|
|
|
FESTIVALS = [
|
|
'Rosh Hashana', 'Yom Kippur', 'Succos', 'Shmini Atzeres', 'Simchas Torah',
|
|
'Chanuka', "Tu B'shvat", 'Purim Katan', 'Purim', 'Shushan Purim',
|
|
'Pesach', 'Pesach Sheni', "Lag Ba'omer", 'Shavuos', "Tu B'av"]
|
|
|
|
|
|
FESTIVALS_HEBREW = [
|
|
'ראש השנה', 'יום כיפור', 'סוכות', 'שמיני עצרת', 'שמחת תורה', 'חנוכה',
|
|
'ט״ו בשבט', 'פורים קטן', 'פורים', 'שושן פורים', 'פסח', 'פסח שני',
|
|
'ל״ג בעומר', 'שבועות', 'ט״ו באב'
|
|
]
|
|
|
|
|
|
WEEKDAYS = {
|
|
1: 'ראשון',
|
|
2: 'שני',
|
|
3: 'שלישי',
|
|
4: 'רביעי',
|
|
5: 'חמישי',
|
|
6: 'שישי',
|
|
7: 'שבת'
|
|
}
|
|
|
|
|
|
def _is_leap(year):
|
|
if (((7*year) + 1) % 19) < 7:
|
|
return True
|
|
return False
|
|
|
|
|
|
def _elapsed_months(year):
|
|
return (235 * year - 234) // 19
|
|
|
|
|
|
@lru_cache(maxsize=10)
|
|
def _elapsed_days(year):
|
|
months_elapsed = _elapsed_months(year)
|
|
parts_elapsed = 204 + 793*(months_elapsed%1080)
|
|
hours_elapsed = (
|
|
5 + 12*months_elapsed + 793*(months_elapsed//1080)
|
|
+ parts_elapsed//1080)
|
|
conjunction_day = 1 + 29*months_elapsed + hours_elapsed//24
|
|
conjunction_parts = 1080 * (hours_elapsed%24) + parts_elapsed%1080
|
|
|
|
if (
|
|
(conjunction_parts >= 19440)
|
|
or (
|
|
(conjunction_day % 7 == 2) and (conjunction_parts >= 9924)
|
|
and not _is_leap(year)
|
|
)
|
|
or (
|
|
(conjunction_day % 7 == 1) and conjunction_parts >= 16789
|
|
and _is_leap(year - 1)
|
|
)
|
|
):
|
|
alt_day = conjunction_day + 1
|
|
else:
|
|
alt_day = conjunction_day
|
|
if alt_day % 7 in [0, 3, 5]:
|
|
alt_day += 1
|
|
|
|
return alt_day
|
|
|
|
|
|
def _days_in_year(year):
|
|
return _elapsed_days(year + 1) - _elapsed_days(year)
|
|
|
|
|
|
def _long_cheshvan(year):
|
|
"""Returns True if Cheshvan has 30 days"""
|
|
return _days_in_year(year) % 10 == 5
|
|
|
|
|
|
def _short_kislev(year):
|
|
"""Returns True if Kislev has 29 days"""
|
|
return _days_in_year(year) % 10 == 3
|
|
|
|
|
|
def _month_length(year, month):
|
|
"""Months start with Nissan (Nissan is 1 and Tishrei is 7)"""
|
|
if month in [1, 3, 5, 7, 11]:
|
|
return 30
|
|
if month in [2, 4, 6, 10, 13]:
|
|
return 29
|
|
if month == 12:
|
|
if _is_leap(year):
|
|
return 30
|
|
return 29
|
|
if month == 8: # if long Cheshvan return 30, else return 29
|
|
if _long_cheshvan(year):
|
|
return 30
|
|
return 29
|
|
if month == 9: # if short Kislev return 29, else return 30
|
|
if _short_kislev(year):
|
|
return 29
|
|
return 30
|
|
raise ValueError('Invalid month')
|
|
|
|
|
|
def _month_name(year, month, hebrew):
|
|
index = month
|
|
if month < 12 or not _is_leap(year):
|
|
index -= 1
|
|
if hebrew:
|
|
return MONTH_NAMES_HEBREW[index]
|
|
return MONTH_NAMES[index]
|
|
|
|
|
|
def _monthslist(year):
|
|
months = [7, 8, 9, 10, 11, 12, 13, 1, 2, 3, 4, 5, 6]
|
|
if not _is_leap(year):
|
|
months.remove(13)
|
|
return months
|
|
|
|
|
|
def _add_months(year, month, num):
|
|
monthslist = _monthslist(year)
|
|
index = monthslist.index(month)
|
|
months_remaining = len(monthslist[index+1:])
|
|
if num <= months_remaining:
|
|
return (year, monthslist[index + num])
|
|
return _add_months(year + 1, 7, num - months_remaining - 1)
|
|
|
|
|
|
def _subtract_months(year, month, num):
|
|
monthslist = _monthslist(year)
|
|
index = monthslist.index(month)
|
|
if num <= index:
|
|
return (year, monthslist[index - num])
|
|
return _subtract_months(year - 1, 6, num - (index+1))
|
|
|
|
|
|
def _fast_day(date):
|
|
"""Return name of fast day or None.
|
|
|
|
Parameters
|
|
----------
|
|
date : ``HebrewDate``, ``GregorianDate``, or ``JulianDay``
|
|
Any date that implements a ``to_heb()`` method which returns a
|
|
``HebrewDate`` can be used.
|
|
|
|
Returns
|
|
-------
|
|
str or ``None``
|
|
The name of the fast day or ``None`` if the given date is not
|
|
a fast day.
|
|
"""
|
|
date = date.to_heb()
|
|
year = date.year
|
|
month = date.month
|
|
day = date.day
|
|
weekday = date.weekday()
|
|
adar = 13 if _is_leap(year) else 12
|
|
|
|
if month == 7:
|
|
if (weekday == 1 and day == 4) or (weekday != 7 and day == 3):
|
|
return _Days.TZOM_GEDALIA
|
|
elif month == 10 and day == 10:
|
|
return _Days.TENTH_OF_TEVES
|
|
elif month == adar:
|
|
if (weekday == 5 and day == 11) or weekday != 7 and day == 13:
|
|
return _Days.TAANIS_ESTHER
|
|
elif month == 4:
|
|
if (weekday == 1 and day == 18) or (weekday != 7 and day == 17):
|
|
return _Days.SEVENTEENTH_OF_TAMUZ
|
|
elif month == 5:
|
|
if (weekday == 1 and day == 10) or (weekday != 7 and day == 9):
|
|
return _Days.NINTH_OF_AV
|
|
return None
|
|
|
|
|
|
def _fast_day_string(date, hebrew=False):
|
|
fast = _fast_day(date)
|
|
if fast is None:
|
|
return None
|
|
if hebrew:
|
|
return _days_hebrew[fast]
|
|
return fast.value
|
|
|
|
|
|
def _first_day_of_holiday(holiday):
|
|
if holiday is _Days.ROSH_HASHANA:
|
|
return (7, 1)
|
|
if holiday is _Days.SUCCOS:
|
|
return (7, 15)
|
|
if holiday is _Days.CHANUKA:
|
|
return (9, 25)
|
|
if holiday is _Days.PESACH:
|
|
return (1, 15)
|
|
if holiday is _Days.SHAVUOS:
|
|
return (3, 6)
|
|
return None
|
|
|
|
|
|
def _festival(date, israel=False, include_working_days=True):
|
|
"""Return Jewish festival of given day.
|
|
|
|
This method will return all major and minor religous
|
|
Jewish holidays not including fast days.
|
|
|
|
Parameters
|
|
----------
|
|
date : ``HebrewDate``, ``GregorianDate``, or ``JulianDay``
|
|
Any date that implements a ``to_heb()`` method which returns a
|
|
``HebrewDate`` can be used.
|
|
|
|
israel : bool, optional
|
|
``True`` if you want the holidays according to the Israel
|
|
schedule. Defaults to ``False``.
|
|
|
|
include_working_days : bool, optional
|
|
``True`` to include festival days in which melacha (work) is
|
|
allowed; ie. Pesach Sheni, Chol Hamoed, etc.
|
|
Default is ``True``.
|
|
|
|
Returns
|
|
-------
|
|
str or ``None``
|
|
The festival or ``None`` if the given date is not a Jewish
|
|
festival.
|
|
"""
|
|
date = date.to_heb()
|
|
year = date.year
|
|
month = date.month
|
|
day = date.day
|
|
if month == 7:
|
|
if day in [1, 2]:
|
|
return _Days.ROSH_HASHANA
|
|
if day == 10:
|
|
return _Days.YOM_KIPPUR
|
|
if (
|
|
not include_working_days
|
|
and (day in range(17, 22) or (israel and day == 16))
|
|
):
|
|
return None
|
|
if day in range(15, 22):
|
|
return _Days.SUCCOS
|
|
if day == 22:
|
|
return _Days.SHMINI_ATZERES
|
|
if day == 23 and not israel:
|
|
return _Days.SIMCHAS_TORAH
|
|
elif month in [9, 10] and include_working_days:
|
|
kislev_length = _month_length(year, 9)
|
|
if (
|
|
month == 9 and day in range(25, kislev_length + 1)
|
|
or month == 10 and day in range(1, 8 - (kislev_length - 25))
|
|
):
|
|
return _Days.CHANUKA
|
|
elif month == 11 and day == 15 and include_working_days:
|
|
return _Days.TU_BSHVAT
|
|
elif month == 12 and include_working_days:
|
|
leap = _is_leap(year)
|
|
if day == 14:
|
|
return _Days.PURIM_KATAN if leap else _Days.PURIM
|
|
if day == 15 and not leap:
|
|
return _Days.SHUSHAN_PURIM
|
|
elif month == 13 and include_working_days:
|
|
if day == 14:
|
|
return _Days.PURIM
|
|
if day == 15:
|
|
return _Days.SHUSHAN_PURIM
|
|
elif month == 1:
|
|
if (
|
|
not include_working_days
|
|
and (day in range(17, 21) or (israel and day == 16))
|
|
):
|
|
return None
|
|
if day in range(15, 22 if israel else 23):
|
|
return _Days.PESACH
|
|
elif month == 2 and day == 14 and include_working_days:
|
|
return _Days.PESACH_SHENI
|
|
elif month == 2 and day == 18 and include_working_days:
|
|
return _Days.LAG_BAOMER
|
|
elif month == 3 and (day == 6 or (not israel and day == 7)):
|
|
return _Days.SHAVUOS
|
|
elif month == 5 and day == 15 and include_working_days:
|
|
return _Days.TU_BAV
|
|
return None
|
|
|
|
|
|
def _festival_string(
|
|
date,
|
|
israel=False,
|
|
hebrew=False,
|
|
include_working_days=True,
|
|
):
|
|
festival = _festival(date, israel, include_working_days)
|
|
if festival is None:
|
|
return None
|
|
if hebrew:
|
|
return _days_hebrew[festival]
|
|
return festival.value
|