o
    �Á›jÂ
  ã                   @   sì   d Z ddlmZmZ ddlmZ ddlmZ dd„ Zdefdd	„Z	d
efdd„Z
dedefdd„Zdededefdd„Zdefdd„Zdefdd„Zdefdd„Zdefdd„Zdefdd„Zdefdd„Zdefdd „Zdefd!d"„Zd#S )$a#  
market_time.py

All schedule/time comparisons go through here so the rest of the code
never does naive string or local-time comparisons (a common source of
"incorrect market-time handling" bugs, especially around DST). Uses
zoneinfo (stdlib, Python 3.9+) with America/New_York from config.
é    )ÚdatetimeÚtime)ÚZoneInfo)Ú
get_configc                   C   s   t tƒ d d ƒS )NÚscheduleÚtimezone)r   r   © r   r   úG/var/www/screener/trade/premarket_backup_2026-09-08_2010/market_time.pyÚ_tz   s   r
   Úreturnc                   C   s   t  tƒ ¡S )N)r   Únowr
   r   r   r   r	   Únow_et   s   r   Údtc                 C   s   |   tƒ ¡ ¡ S )z¼Trading-day date for an arbitrary (tz-aware) timestamp, e.g. a
    UTC exit_time/updated_at pulled from persisted state, converted to
    the exchange's own calendar day rather than UTC's.)Ú
astimezoner
   Údate)r   r   r   r	   Úet_date   s   r   Úhhmmssc                 C   s&   dd„ |   d¡D ƒ\}}}t|||ƒS )Nc                 S   s   g | ]}t |ƒ‘qS r   )Úint)Ú.0Úxr   r   r	   Ú
<listcomp>    s    z_parse_time.<locals>.<listcomp>ú:)ÚsplitÚdtime)r   ÚhÚmÚsr   r   r	   Ú_parse_time   s   r   Úcurrentc                 C   s   |   ¡ jd d�t|ƒkS )N)Útzinfo)ÚtimetzÚreplacer   )r   r   r   r   r	   Ú	_is_after$   s   r"   c                  C   ó   t ƒ d } ttƒ | d ƒS )Nr   Úpremarket_scan_time©r   r"   r   ©Úcfgr   r   r	   Úis_premarket_scan_time(   ó   
r(   c                  C   s.   t ƒ d } tƒ }t|| d ƒot|| d ƒ S )Nr   Úmarket_open_timeÚmarket_close_time)r   r   r"   )r'   r   r   r   r	   Úis_market_open-   s   
r,   c                  C   r#   )Nr   r*   r%   r&   r   r   r	   Úis_past_market_open3   r)   r-   c                  C   r#   )Nr   Úno_new_entries_afterr%   r&   r   r   r	   Úis_new_entries_cutoff8   r)   r/   c                  C   r#   )Nr   Úforce_liquidate_timer%   r&   r   r   r	   Úis_force_liquidate_time=   r)   r1   c                  C   r#   )Nr   r+   r%   r&   r   r   r	   Úis_market_closed_for_dayB   r)   r2   c                   C   s   t ƒ  ¡ dk S )Né   )r   Úweekdayr   r   r   r	   Ú
is_weekdayG   s   r5   c                  C   sD   t ƒ d } t| d ƒ}tƒ }|j|j|j|jdd�}||  ¡ d S )a�  [FEATURE 2026-09-05] Minutes since market_open_time today, for
    regime_engine.classify_regime()'s session_elapsed_minutes param (its
    OPENING_VOLATILITY window check). Negative before the open -- callers
    that only care about "are we in the opening window" should treat a
    negative value the same as regime_engine already treats None (can't
    be in the opening window if the session hasn't started).r   r*   r   )ÚhourÚminuteÚsecondÚmicrosecondg      N@)r   r   r   r!   r6   r7   r8   Útotal_seconds)r'   Ú	open_timer   Úopen_dtr   r   r	   Úminutes_since_openK   s   
ÿr=   N)Ú__doc__r   r   r   Úzoneinfor   Úconfig_loaderr   r
   r   r   Ústrr   Úboolr"   r(   r,   r-   r/   r1   r2   r5   Úfloatr=   r   r   r   r	   Ú<module>   s"    	