Skip to content

Instantly share code, notes, and snippets.

@paulate
Last active October 21, 2025 03:07
Show Gist options
  • Select an option

  • Save paulate/cf7289a212851bde8bebf2a43134e8b0 to your computer and use it in GitHub Desktop.

Select an option

Save paulate/cf7289a212851bde8bebf2a43134e8b0 to your computer and use it in GitHub Desktop.
# For "How does this Balinese calendar work?" Dinachronicle 4 @ Dinacon 2025
# Below is a lil python script to calculate your Pawukon birthday from your Gregorian birthday.
# Just run: python pawukon.py yyyy-mm-dd
# If you announce your birthday to the locals and it’s clearly an unlucky day, they may change
# your day to a more auspicious one!
from datetime import datetime, date
class PawukonConverter:
def __init__(self):
# Define the cycles
self.saptawara = ["Redite", "Soma", "Anggara", "Buda", "Wraspati", "Sukra", "Saniscara"]
self.pancawara = ["Paing", "Pon", "Wage", "Keliwon", "Umanis"]
self.wuku = [
"Sinta", "Landep", "Ukir", "Kulantir", "Tolu", "Gumbreg", "Wariga", "Warigadean",
"Julungwangi", "Sungsang", "Dungulan", "Kuningan", "Langkir", "Medangsia", "Pujut",
"Pahang", "Krulut", "Mrakih", "Tambir", "Madangkungan", "Matal", "Uye", "Manail",
"Perangbakat", "Bala", "Ugu", "Wayang", "Klawu", "Dukut", "Watugunung"
]
# Reference date: July 1, 2025 = Anggara Wage Matal
self.reference_date = date(2025, 7, 1)
self.reference_saptawara = "Anggara" # index 2
self.reference_pancawara = "Wage" # index 2
self.reference_wuku = "Matal" # index 20
# Get reference indices
self.ref_saptawara_idx = self.saptawara.index(self.reference_saptawara)
self.ref_pancawara_idx = self.pancawara.index(self.reference_pancawara)
self.ref_wuku_idx = self.wuku.index(self.reference_wuku)
def convert_date(self, input_date):
"""
Convert a Gregorian date to Pawukon system
Args:
input_date: datetime.date object or string in format 'YYYY-MM-DD'
Returns:
tuple: (saptawara, pancawara, wuku)
"""
if isinstance(input_date, str):
input_date = datetime.strptime(input_date, '%Y-%m-%d').date()
# Calculate days difference from reference date
days_diff = (input_date - self.reference_date).days
# Calculate indices for each cycle
saptawara_idx = (self.ref_saptawara_idx + days_diff) % len(self.saptawara)
pancawara_idx = (self.ref_pancawara_idx + days_diff) % len(self.pancawara)
# Wuku changes every 7 days (it's a week-based cycle)
weeks_diff = days_diff // 7
wuku_idx = (self.ref_wuku_idx + weeks_diff) % len(self.wuku)
return (
self.saptawara[saptawara_idx],
self.pancawara[pancawara_idx],
self.wuku[wuku_idx]
)
def get_wuku_week_info(self, wuku_name):
"""
Get additional information about the wuku
Args:
wuku_name: string name of the wuku
Returns:
dict: information about the wuku
"""
wuku_idx = self.wuku.index(wuku_name)
return {
'name': wuku_name,
'number': wuku_idx + 1,
'position': f"Week {wuku_idx + 1} of 30"
}
def format_result(self, gregorian_date, saptawara, pancawara, wuku, compact=False):
"""
Format the conversion result nicely
Args:
gregorian_date: input date
saptawara: saptawara result
pancawara: pancawara result
wuku: wuku result
compact: if True, return compact single-line format
"""
if compact:
return f"{gregorian_date}{saptawara} {pancawara} {wuku}"
wuku_info = self.get_wuku_week_info(wuku)
result = f"""
Gregorian Date: {gregorian_date}
Pawukon Date: {saptawara} {pancawara} {wuku}
Details:
- Saptawara (7-day cycle): {saptawara}
- Pancawara (5-day cycle): {pancawara}
- Wuku (30-week cycle): {wuku} ({wuku_info['position']})
"""
return result.strip()
# Example usage and testing
def main():
converter = PawukonConverter()
# Test with the reference date
print("=== Testing Reference Date ===")
ref_result = converter.convert_date(date(2025, 7, 1))
print(converter.format_result(date(2025, 7, 1), *ref_result))
print("\n=== Testing Other Dates ===")
# Test with some other dates
test_dates = [
"2025-07-02", # Next day
"2025-07-08", # One week later
"2025-06-30", # Day before
"2025-08-01", # One month later
"2024-07-01", # One year earlier
"2026-07-01" # One year later
]
for test_date in test_dates:
result = converter.convert_date(test_date)
print(converter.format_result(test_date, *result))
print()
# Interactive function
def interactive_converter():
"""
Interactive date converter
"""
converter = PawukonConverter()
print("=== Pawukon Date Converter ===")
print("Enter dates in YYYY-MM-DD format (or 'quit' to exit)")
while True:
user_input = input("\nEnter Gregorian date: ").strip()
if user_input.lower() == 'quit':
break
try:
result = converter.convert_date(user_input)
print(converter.format_result(user_input, *result))
except ValueError as e:
print(f"Error: Invalid date format. Please use YYYY-MM-DD format.")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
import sys
if len(sys.argv) == 1:
# No arguments - run interactive mode
interactive_converter()
elif len(sys.argv) == 2:
# One argument - convert single date
try:
converter = PawukonConverter()
input_date = sys.argv[1]
result = converter.convert_date(input_date)
print(converter.format_result(input_date, *result))
except ValueError:
print("Error: Invalid date format. Please use YYYY-MM-DD format.")
sys.exit(1)
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
elif len(sys.argv) > 2:
# Multiple arguments - convert multiple dates
converter = PawukonConverter()
for date_str in sys.argv[1:]:
try:
result = converter.convert_date(date_str)
print(converter.format_result(date_str, *result))
print() # Empty line between results
except ValueError:
print(f"Error: Invalid date format '{date_str}'. Please use YYYY-MM-DD format.")
except Exception as e:
print(f"Error converting '{date_str}': {e}")
else:
print("Usage:")
print(" python pawukon.py # Interactive mode")
print(" python pawukon.py 2025-01-01 # Convert single date")
print(" python pawukon.py 2025-01-01 2025-01-02 # Convert multiple dates")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment