Census Calculator

Garland Joseph

This program will input a 4-digit year and then relate the generations of your ancestors to the particular United States Census

#Garland R. Joseph | garland.joseph@gmail.com
#October 10,  2025
# This program will input a 4-digit year and then relate 
# the generations of your ancestors 
# to the particular United States Census



import math
from datetime import datetime

def calculate_ancestral_census(birth_year, generations, generation_length=30):
    """
    Calculate ancestral census information based on birth year and generations.
    
    Args:
        birth_year (int): The birth year of the starting person
        generations (int): Number of generations to calculate back
        generation_length (int): Average years per generation (default: 30)
    
    Returns:
        list: List of dictionaries containing ancestral census data
    """
    
    # Get current year for validation
    current_year = datetime.now().year
    
    # Validate input
    if birth_year < 1700 or birth_year > current_year:
        raise ValueError(f"Birth year must be between 1700 and {current_year}")
    
    if generations < 1 or generations > 10:
        raise ValueError("Generations must be between 1 and 10")
    
    if generation_length < 20 or generation_length > 40:
        raise ValueError("Generation length must be between 20 and 40 years")
    
    results = []
    
    for gen in range(1, generations + 1):
        # Calculate ancestor's approximate birth year
        ancestor_birth = birth_year - (gen * generation_length)
        
        # Calculate first census where they would appear as a child (age 0-9)
        # Using the formula: ROUNDUP((birth_year + 1) / 10) × 10
        first_census = math.ceil((ancestor_birth + 1) / 10) * 10
        
        # Calculate their age in that census
        age_in_census = first_census - ancestor_birth
        
        # Determine relationship label
        if gen == 1:
            relationship = "Parent"
        elif gen == 2:
            relationship = "Grandparent"
        elif gen == 3:
            relationship = "Great-Grandparent"
        else:
            relationship = f"{gen-1}x Great-Grandparent"
        
        # Add historical context notes
        notes = []
        if first_census < 1790:
            notes.append("Before first US census")
        elif first_census < 1850:
            notes.append("Pre-1850: Only head of household named")
        elif first_census == 1890:
            notes.append("1890 Census mostly destroyed by fire")
        elif first_census == 1950:
            notes.append("1950 Census is most recently available")
        elif first_census > 1950:
            notes.append("Census not yet publicly available (72-year rule)")
        
        results.append({
            'generation': gen,
            'relationship': relationship,
            'approx_birth_year': ancestor_birth,
            'first_census': first_census,
            'age_in_census': age_in_census,
            'notes': notes
        })
    
    return results

def display_results(birth_year, generations, generation_length, results):
    """Display the results in a formatted table."""
    
    print("\n" + "="*80)
    print(f"ANCESTRAL CENSUS CALCULATOR")
    print(f"Starting Birth Year: {birth_year}")
    print(f"Generations to Calculate: {generations}")
    print(f"Generation Length: {generation_length} years")
    print("="*80)
    
    print(f"\n{'Gen':<4} {'Relationship':<20} {'Approx Birth':<14} {'First Census':<12} {'Age':<6} Notes")
    print("-" * 80)
    
    for result in results:
        notes = "; ".join(result['notes']) if result['notes'] else ""
        print(f"{result['generation']:<4} {result['relationship']:<20} {result['approx_birth_year']:<14} {result['first_census']:<12} {result['age_in_census']:<6} {notes}")

def main():
    """Main function to run the ancestral census calculator."""
    
    print("ANCESTRAL CENSUS CALCULATOR")
    print("This program calculates when your ancestors would appear in US census records.")
    print("Default generation length is 30 years. US Censuses occur every 10 years (1790, 1800, etc.)")
    print("-" * 60)
    
    try:
        # Get user input
        birth_year = int(input("Enter the starting birth year (e.g., 1962): "))
        generations = int(input("Enter number of generations to calculate (1-10): "))
        
        use_default = input("Use default 30-year generation length? (y/n): ").lower().strip()
        if use_default == 'y':
            generation_length = 30
        else:
            generation_length = int(input("Enter generation length in years (20-40): "))
        
        # Calculate results
        results = calculate_ancestral_census(birth_year, generations, generation_length)
        
        # Display results
        display_results(birth_year, generations, generation_length, results)
        
        # Additional information
        print("\n" + "="*80)
        print("IMPORTANT NOTES:")
        print("- Censuses before 1850 only listed the head of household by name")
        print("- The 1890 US Census was mostly destroyed by fire")
        print("- Census records are publicly available after 72 years (1950 is latest)")
        print("- These are approximations - actual family patterns may vary")
        print("="*80)
        
    except ValueError as e:
        print(f"Error: {e}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")

# Example usage function
def run_example():
    """Run an example with predefined values."""
    print("Running example for birth year 1962, 5 generations:")
    results = calculate_ancestral_census(1962, 5)
    display_results(1962, 5, 30, results)

if __name__ == "__main__":
    # Uncomment the next line to run an example instead of interactive input
    # run_example()
    
    main()