Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| from dash import html | |
| def ordinal(n: int) -> str: | |
| """Return the ordinal suffix for a day (e.g., 1 -> 1st).""" | |
| if 10 <= n % 100 <= 20: | |
| suffix = "th" | |
| else: | |
| suffix = {1: "st", 2: "nd", 3: "rd"}.get(n % 10, "th") | |
| return f"{n}{suffix}" | |
| def format_date(dt: pd.Timestamp) -> str: | |
| """Format a pandas Timestamp into a readable string.""" | |
| return dt.strftime("%b") + f" {ordinal(dt.day)}, {dt.year}" | |
| def build_slider_marks(start_dt: pd.Timestamp, end_dt: pd.Timestamp): | |
| """Create slider marks for the range and all-time sliders.""" | |
| return [ | |
| {"value": int(start_dt.timestamp()), "label": start_dt.strftime("%b %Y")}, | |
| {"value": int(end_dt.timestamp()), "label": end_dt.strftime("%b %Y")}, | |
| ] | |
| def get_thumb_labels(values): | |
| """Generate thumb labels for the range slider.""" | |
| distance = abs(values[1] - values[0]) | |
| close = distance < 4 * 30 * 86400 # 4 months | |
| label_style = { | |
| "background": "#fff", | |
| "color": "#082030", | |
| "fontWeight": "bold", | |
| "fontSize": "13px", | |
| "borderRadius": "8px", | |
| "padding": "2px 8px", | |
| "boxShadow": "0 1px 4px rgba(8,32,48,0.10)", | |
| "position": "absolute", | |
| "left": "50%", | |
| "transform": "translateX(-50%)", | |
| "whiteSpace": "nowrap", | |
| "zIndex": 100, | |
| } | |
| if close: | |
| style_top_1 = label_style.copy() | |
| style_top_1["top"] = "-38px" | |
| style_top_2 = label_style.copy() | |
| style_top_2["top"] = "14px" | |
| else: | |
| style_top_1 = label_style.copy() | |
| style_top_1["top"] = "14px" | |
| style_top_2 = label_style.copy() | |
| style_top_2["top"] = "14px" | |
| return [ | |
| html.Div(pd.to_datetime(values[0], unit="s").strftime("%b %d, %Y"), style=style_top_1), | |
| html.Div(pd.to_datetime(values[1], unit="s").strftime("%b %d, %Y"), style=style_top_2), | |
| ] | |
| def get_thumb_label_single(value): | |
| """Generate thumb label for the all-time slider.""" | |
| label_style = { | |
| "background": "#fff", | |
| "color": "#082030", | |
| "fontWeight": "bold", | |
| "fontSize": "13px", | |
| "borderRadius": "8px", | |
| "padding": "2px 8px", | |
| "boxShadow": "0 1px 4px rgba(8,32,48,0.10)", | |
| "position": "absolute", | |
| "left": "50%", | |
| "transform": "translateX(-50%)", | |
| "whiteSpace": "nowrap", | |
| "zIndex": 100, | |
| "top": "14px", | |
| } | |
| return [html.Div(pd.to_datetime(value, unit="s").strftime("%b %d, %Y"), style=label_style)] | |
| def format_large_number(n: int) -> str: | |
| """Shorten large numbers, e.g. 5,000,000 -> '5 million'.""" | |
| if n >= 1_000_000_000: | |
| return f"{n / 1_000_000_000:.1f} billion" | |
| if n >= 1_000_000: | |
| return f"{n / 1_000_000:.1f} million" | |
| if n >= 1_000: | |
| return f"{n / 1_000:.1f}k" | |
| return str(int(n)) | |