In the beginning [time] was created. This has made a lot of people very angry and has been widely regarded as a bad move.
-- Douglas Adams, The Restaurant at the End of the Universe
Since astrodynamics is the study of the motion of objects in space, time is a fundamental quantity to the package. Unfortunately, time can quickly become a complex topic with many different time systems, formats, and conventions.
Brahe attempts to solve this challenge by providing the Epoch class to represent a single instant in time. An Epoch can be initialized in a variety of ways, it can be manipulated with simple arithmetic operations, and and it can be compared to other Epoch instances. Brahe ensures that all of the complexities of time systems, formats, and conventions are handled internally by the Epoch class so that users can work with time in a simple and intuitive way.
There are more ways to work with Epochs and time than are covered here. Checkout the Time User Guide or the API Reference for more details and examples of working with time in Brahe.
importbraheasbhfromdatetimeimportdatetime# Create from calendar dateepoch_1=bh.Epoch(2024,1,1)epoch_2=bh.Epoch(2024,1,1,0,0,0)# Create from ISO 8601 stringepoch_3=bh.Epoch("2024-01-01T00:00:00Z")# Create from string with time systemepoch_4=bh.Epoch("2024-01-00 00:00:00 GPS")# Create from datetimeepoch_5=bh.Epoch(datetime(2024,1,1,0,0,0))# Current instantepoch_6=bh.Epoch.now()
#[allow(unused_imports)]usebraheasbh;fnmain(){// Create from calendar datelet_epoch_1=bh::Epoch::from_date(2024,1,1,bh::TimeSystem::UTC);let_epoch_2=bh::Epoch::from_datetime(2024,1,1,0,0,0.0,0.0,bh::TimeSystem::UTC);// // Create from ISO 8601 stringlet_epoch_3=bh::Epoch::from_string("2024-01-01T00:00:00Z");// Create from String with time systemlet_epoch_4=bh::Epoch::from_string("2024-01-00 00:00:00 GPS");// Current instantlet_epoch_5=bh::Epoch::now();}
importbraheasbh# Initialize EOPbh.initialize_eop()# Start with an epochepoch=bh.Epoch(2024,1,1)# Add time (in seconds)epoch_plus_1_day=epoch+86400# Add one dayepoch_plus_1_hour=epoch+3600# Add one hourepoch_plus_1_ns=epoch+1e-9# Add one nanosecond# Subtract time (in seconds)epoch_minus_1_day=epoch-86400# Subtract one dayepoch_minus_1_hour=epoch-3600# Subtract one hourepoch_minus_1_ns=epoch-1e-9# Subtract one nan# Get difference between two epochs (in seconds)difference=epoch_plus_1_day-epoch# Should be 86400 secondsprint(f"Difference in seconds: {difference:.2f}")# Comparison operationsprint(f"epoch < epoch_plus_1_day: {epoch<epoch_plus_1_day}")print(f"epoch == epoch_minus_1_day: {epoch==epoch_minus_1_day}")print(f"epoch > epoch_minus_1_day: {epoch>epoch_minus_1_day}")
#[allow(unused_imports)]usebraheasbh;fnmain(){// Initialize EOP providerbh::initialize_eop().unwrap();// Create from calendar dateletepoch=bh::Epoch::from_date(2024,1,1,bh::TimeSystem::UTC);// Add time (in seconds)letepoch_plus_1_day=epoch+86400.0;// Add one daylet_epoch_plus_1_hour=epoch+3600.0;// Add one hourlet_epoch_plus_1_ns=epoch+1e-9;// Add one nanosecond// Subtract time (in seconds)let_epoch_minus_1_day=epoch-86400.0;// Subtract one daylet_epoch_minus_1_hour=epoch-3600.0;// Subtract one hourlet_epoch_minus_1_ns=epoch-1e-9;// Subtract one nanosecond// Get difference between two epochs (in seconds)letdifference=epoch_plus_1_day-epoch;// Should be 86400 secondsprintln!("Difference in seconds: {:.2}",difference);// Comparison operationsprintln!("epoch < epoch_plus_1_day: {}",epoch<epoch_plus_1_day);println!("epoch == epoch_minus_1_day: {}",epoch==_epoch_minus_1_day);println!("epoch > epoch_minus_1_day: {}",epoch>_epoch_minus_1_day);}
importbraheasbh# Create an Epochepoch=bh.Epoch(2024,1,1)# Output as iso stringprint(f"Epoch as ISO 8601 string: {epoch}")# Output as Modified Julian Dateprint(f"Epoch as Modified Julian Date: {epoch.mjd()}")# Output as calendar dateprint(f"Epoch as calendar date tuple: {epoch.to_datetime()}")# Output as UNIX timestampprint(f"Epoch as UNIX timestamp: {epoch.unix_timestamp()}")# Output as GPS timeprint(f"Epoch as GPS time: {epoch.gps_date()}")# Output as Python datetimeprint(f"Epoch as Python datetime: {epoch.to_pydatetime()}")
#[allow(unused_imports)]usebraheasbh;fnmain(){// Create an Epochletepoch=bh::Epoch::from_date(2024,1,1,bh::TimeSystem::UTC);// Output as iso stringprintln!("Epoch as ISO 8601 string: {}",epoch);// Output as Modified Julian Dateprintln!("Epoch as Modified Julian Date: {}",epoch.mjd());// Output as calendar dateprintln!("Epoch as calendar date tuple: {:?}",epoch.to_datetime());// Output as UNIX timestampprintln!("Epoch as UNIX timestamp: {}",epoch.unix_timestamp());// Output as GPS timeprintln!("Epoch as GPS time: {:?}",epoch.gps_date());}
Epoch as ISO 8601 string: 2024-01-01 00:00:00.000 UTC
Epoch as Modified Julian Date: 60310.0
Epoch as calendar date tuple: (2024, 1, 1, 0, 0, 0.0, 0.0)
Epoch as UNIX timestamp: 1704067200.0
Epoch as GPS time: (2295, 86417.99999980722)
Epoch as Python datetime: 2024-01-01 00:00:00+00:00
Epoch as ISO 8601 string: 2024-01-01 00:00:00.000 UTC
Epoch as Modified Julian Date: 60310
Epoch as calendar date tuple: (2024, 1, 1, 0, 0, 0.0, 0.0)
Epoch as UNIX timestamp: 1704067200
Epoch as GPS time: (2295, 86417.99999980722)
importbraheasbh# Initialize EOPbh.initialize_eop()# Get epochs in a range every 6 hours# Just like python's range it is inclusive of the start and exclusive of the endforepochinbh.TimeRange(bh.Epoch(2024,1,1),bh.Epoch(2024,1,2),6*3600):print(epoch)
#[allow(unused_imports)]usebraheasbh;fnmain(){// Initialize EOP providerbh::initialize_eop().unwrap();// Get epochs in a range every 6 hours// It is inclusive of the start and exclusive of the endforepochinbh::TimeRange::new(bh::Epoch::from_date(2024,1,1,bh::TimeSystem::UTC),bh::Epoch::from_date(2024,1,2,bh::TimeSystem::UTC),6.0*3600.0){println!("{}",epoch);}}
In astrodynamics, we often deal with models and measurements in other time systems (e.g. GPS, TAI, TT, etc.). Brahe provides support for working with different time systems through the TimeSystem enum. When creating an Epoch, you can specify the time system of the input time, and Brahe will handle the conversion to the internal time system (TAI) for you. Similarly when outputting an Epoch, you can specify the desired time system for the output, and Brahe will handle the conversion for you. Comparisons between Epoch instances are time-system aware, so you can compare Epoch instances in different time systems and Brahe will handle the conversion for you.