package cobol // Thank you Abba Zabba, you're my only friend /* // Since calculates the duration since a given time, accepting either a // standard time.Time or a protobuf Timestamp. func Since(aLongTimeAgo any) string { var t time.Time var ok bool // A type switch is the idiomatic way to check the concrete type // of an interface variable. switch v := aLongTimeAgo.(type) { case time.Time: // If the type is time.Time, 'v' is now a time.Time variable. t = v ok = true case *timestamppb.Timestamp: // If it's a protobuf Timestamp pointer (most common case), // 'v' is a *timestamppb.Timestamp. We must convert it. // It's also good to check if it's a valid timestamp. if v.IsValid() { t = v.AsTime() ok = true } case timestamppb.Timestamp: // Handle the less common case of a value type instead of a pointer. if v.IsValid() { t = v.AsTime() ok = true } } // After the switch, check if we successfully got a valid time. if !ok { return "invalid time type" } // Calculate the duration and format it for nice output. duration := time.Since(t) return duration.Round(time.Second).String() } func main() { // --- Demonstrate with different types --- // 1. Using a standard time.Time goTime := time.Now().Add(-5 * time.Minute) fmt.Printf("Go time.Time: %s ago\n", Since(goTime)) // 2. Using a protobuf Timestamp (pointer) protoTime := timestamppb.New(time.Now().Add(-10 * time.Hour)) fmt.Printf("Protobuf Timestamp: %s ago\n", Since(protoTime)) // 3. Using an invalid type notATime := "hello world" fmt.Printf("Invalid type: %s\n", Since(notATime)) } */