awacke1 commited on
Commit
d5da5b3
Β·
verified Β·
1 Parent(s): be7db56

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +151 -0
app.py CHANGED
@@ -796,6 +796,157 @@ def list_files_by_type(directory: str = ".",
796
 
797
 
798
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
799
  # ─────────────────────────────────────────────────────────
800
  # 4. PAPER PROCESSING & DISPLAY
801
  # ──────────────────��──────────────────────────────────────
 
796
 
797
 
798
 
799
+
800
+
801
+ def get_central_time() -> datetime:
802
+ """Get current time in US Central timezone."""
803
+ central = pytz.timezone('US/Central')
804
+ return datetime.now(central)
805
+
806
+ def format_timestamp_prefix() -> str:
807
+ """Generate timestamp prefix in format MM_dd_yy_hh_mm_AM/PM."""
808
+ ct = get_central_time()
809
+ return ct.strftime("%m_%d_%y_%I_%M_%p")
810
+
811
+ def get_formatted_time(dt: datetime = None,
812
+ timezone: str = 'US/Central',
813
+ include_timezone: bool = True,
814
+ include_seconds: bool = False) -> str:
815
+ """
816
+ Format a datetime object with specified options.
817
+ If no datetime is provided, uses current time.
818
+ """
819
+ if dt is None:
820
+ tz = pytz.timezone(timezone)
821
+ dt = datetime.now(tz)
822
+ elif dt.tzinfo is None:
823
+ tz = pytz.timezone(timezone)
824
+ dt = tz.localize(dt)
825
+
826
+ format_string = "%Y-%m-%d %I:%M"
827
+ if include_seconds:
828
+ format_string += ":%S"
829
+ format_string += " %p"
830
+ if include_timezone:
831
+ format_string += " %Z"
832
+
833
+ return dt.strftime(format_string)
834
+
835
+ def parse_timestamp(timestamp_str: str,
836
+ timezone: str = 'US/Central') -> Optional[datetime]:
837
+ """
838
+ Parse a timestamp string in various formats.
839
+ Returns timezone-aware datetime object.
840
+ """
841
+ try:
842
+ # Try different format patterns
843
+ patterns = [
844
+ "%m_%d_%y_%I_%M_%p", # Standard app format
845
+ "%Y-%m-%d %I:%M %p", # Common 12-hour format
846
+ "%Y-%m-%d %H:%M", # 24-hour format
847
+ "%m/%d/%y %I:%M %p", # US date format
848
+ "%d/%m/%y %I:%M %p" # European date format
849
+ ]
850
+
851
+ dt = None
852
+ for pattern in patterns:
853
+ try:
854
+ dt = datetime.strptime(timestamp_str, pattern)
855
+ break
856
+ except ValueError:
857
+ continue
858
+
859
+ if dt is None:
860
+ raise ValueError(f"Could not parse timestamp: {timestamp_str}")
861
+
862
+ # Add timezone if not present
863
+ if dt.tzinfo is None:
864
+ tz = pytz.timezone(timezone)
865
+ dt = tz.localize(dt)
866
+
867
+ return dt
868
+
869
+ except Exception as e:
870
+ st.error(f"Error parsing timestamp: {str(e)}")
871
+ return None
872
+
873
+ def get_time_ago(dt: datetime) -> str:
874
+ """
875
+ Convert datetime to human-readable "time ago" format.
876
+ E.g., "2 hours ago", "3 days ago", etc.
877
+ """
878
+ try:
879
+ now = datetime.now(dt.tzinfo)
880
+ diff = now - dt
881
+
882
+ seconds = diff.total_seconds()
883
+
884
+ if seconds < 60:
885
+ return "just now"
886
+ elif seconds < 3600:
887
+ minutes = int(seconds / 60)
888
+ return f"{minutes} minute{'s' if minutes != 1 else ''} ago"
889
+ elif seconds < 86400:
890
+ hours = int(seconds / 3600)
891
+ return f"{hours} hour{'s' if hours != 1 else ''} ago"
892
+ elif seconds < 604800:
893
+ days = int(seconds / 86400)
894
+ return f"{days} day{'s' if days != 1 else ''} ago"
895
+ elif seconds < 2592000:
896
+ weeks = int(seconds / 604800)
897
+ return f"{weeks} week{'s' if weeks != 1 else ''} ago"
898
+ elif seconds < 31536000:
899
+ months = int(seconds / 2592000)
900
+ return f"{months} month{'s' if months != 1 else ''} ago"
901
+ else:
902
+ years = int(seconds / 31536000)
903
+ return f"{years} year{'s' if years != 1 else ''} ago"
904
+
905
+ except Exception as e:
906
+ st.error(f"Error calculating time ago: {str(e)}")
907
+ return "unknown time ago"
908
+
909
+ def format_duration(seconds: float) -> str:
910
+ """
911
+ Format a duration in seconds to human-readable string.
912
+ E.g., "2m 30s", "1h 15m", etc.
913
+ """
914
+ try:
915
+ if seconds < 0:
916
+ return "invalid duration"
917
+
918
+ # Handle special cases
919
+ if seconds < 1:
920
+ return f"{seconds * 1000:.0f}ms"
921
+ if seconds < 60:
922
+ return f"{seconds:.1f}s"
923
+
924
+ # Calculate hours, minutes, seconds
925
+ hours = int(seconds // 3600)
926
+ minutes = int((seconds % 3600) // 60)
927
+ secs = seconds % 60
928
+
929
+ # Build duration string
930
+ parts = []
931
+ if hours > 0:
932
+ parts.append(f"{hours}h")
933
+ if minutes > 0:
934
+ parts.append(f"{minutes}m")
935
+ if secs > 0 and hours == 0: # Only show seconds if less than an hour
936
+ parts.append(f"{secs:.1f}s")
937
+
938
+ return " ".join(parts)
939
+
940
+ except Exception as e:
941
+ st.error(f"Error formatting duration: {str(e)}")
942
+ return "unknown duration"
943
+
944
+
945
+
946
+
947
+
948
+
949
+
950
  # ─────────────────────────────────────────────────────────
951
  # 4. PAPER PROCESSING & DISPLAY
952
  # ──────────────────��──────────────────────────────────────