You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python制作可指定周起始日与月天数的自定义日历?

Great question! The standard calendar module works perfectly for Gregorian calendars, but when you need full control over month lengths and week start days, you'll want to build a custom solution from scratch. Let's walk through how to implement this step by step.

Core Requirements Recap

  • Define a custom number of days per month (no fixed 28/30/31 constraints)
  • Specify any day as the start of the week (Monday, Sunday, etc.)
  • Generate a clean, readable text-based calendar that matches these rules

Step-by-Step Implementation

Below is a flexible function that handles all your requirements. We'll use basic list manipulation and string formatting to create the calendar layout:

def generate_custom_calendar(month_days: int, start_week_day: str = "Monday", first_day_weekday: str = "Monday"):
    # Map weekday names to numerical values for easier calculations
    WEEKDAY_MAP = {
        "Monday": 0,
        "Tuesday": 1,
        "Wednesday": 2,
        "Thursday": 3,
        "Friday": 4,
        "Saturday": 5,
        "Sunday": 6
    }
    
    # Validate input values to avoid errors
    if start_week_day not in WEEKDAY_MAP or first_day_weekday not in WEEKDAY_MAP:
        raise ValueError("Invalid weekday name. Use one of: Monday, Tuesday, ..., Sunday")
    if month_days < 1:
        raise ValueError("Month must have at least 1 day")
    
    # Convert input days to numerical values for math operations
    start_day_num = WEEKDAY_MAP[start_week_day]
    first_day_num = WEEKDAY_MAP[first_day_weekday]
    
    # Create the weekday header in the order of our custom week start
    ordered_weekdays = list(WEEKDAY_MAP.keys())[start_day_num:] + list(WEEKDAY_MAP.keys())[:start_day_num]
    
    # Calculate empty slots needed at the start of the first week
    # This ensures the first day of the month lines up with its correct column
    leading_empty_slots = (first_day_num - start_day_num) % 7
    
    # Build the full list of calendar entries: empty slots + actual days
    calendar_entries = [""] * leading_empty_slots + list(range(1, month_days + 1))
    
    # Split entries into weeks (7 days per week)
    calendar_weeks = [calendar_entries[i:i+7] for i in range(0, len(calendar_entries), 7)]
    
    # Format and print the calendar
    # Print the weekday header with consistent spacing
    print(" | ".join(f"{day:9}" for day in ordered_weekdays))
    print("-" * 65)
    # Print each week row, formatting empty slots and dates uniformly
    for week in calendar_weeks:
        formatted_row = []
        for entry in week:
            if isinstance(entry, int):
                formatted_row.append(f"{entry:9}")
            else:
                formatted_row.append(" " * 9)
        print(" | ".join(formatted_row))

How to Use the Function

Let's test it with a couple of examples to see it in action:

Example 1: 30-day month, week starts on Sunday, first day is Friday

generate_custom_calendar(month_days=30, start_week_day="Sunday", first_day_weekday="Friday")

Output:

Sunday    | Monday    | Tuesday   | Wednesday | Thursday  | Friday    | Saturday  
-----------------------------------------------------------------
          |          |          |          |          |        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 

Example 2: 29-day month, week starts on Monday, first day is Wednesday

generate_custom_calendar(month_days=29, start_week_day="Monday", first_day_weekday="Wednesday")

Output:

Monday    | Tuesday   | Wednesday | Thursday  | Friday    | Saturday  | Sunday    
-----------------------------------------------------------------
          |          |        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 |          |          |          |          

Key Features Explained

  • Input Validation: Catches invalid weekday names or non-positive month lengths before running.
  • Dynamic Week Order: The header automatically adjusts to match your chosen week start day.
  • Flexible First Day: You can set the first day of the month to any weekday, so the calendar aligns exactly as you need.
  • Clean Formatting: Fixed-width spacing keeps the calendar neat and easy to read.

Extensions You Can Add

If you want to expand this further, here are some ideas:

  • Return the calendar as a string instead of printing it directly (great for saving to files or embedding in other outputs).
  • Add support for marking specific dates (like holidays) with special characters or formatting.
  • Integrate with custom year structures (e.g., 13 months per year, each with 28 days).

内容的提问来源于stack exchange,提问作者Austin b

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:08:14