package ted import ( "fmt" "strconv" "strings" "time" ) // parseDate parses various date formats used in TED XML func ParseDate(dateStr string) (time.Time, error) { if dateStr == "" { return time.Time{}, fmt.Errorf("empty date string") } // Common TED date formats formats := []string{ "2006-01-02+07:00", "2006-01-02-07:00", "2006-01-02T15:04:05+07:00", "2006-01-02T15:04:05-07:00", "2006-01-02T15:04:05Z", "2006-01-02Z", "2006-01-02", time.RFC3339, time.RFC3339Nano, } for _, format := range formats { if parsedTime, err := time.Parse(format, dateStr); err == nil { return parsedTime, nil } } return time.Time{}, fmt.Errorf("unable to parse date: %s", dateStr) } // parseDateToUnixMilli converts string date to Unix milliseconds (int64) func ParseDateToUnix(dateStr string) int64 { if dateStr == "" { return 0 } if parsedTime, err := ParseDate(dateStr); err == nil { return parsedTime.Unix() } return 0 } // parseTimeToUnix converts string time to Unix milliseconds (int64) func ParseTimeToUnix(timeStr string) int64 { if timeStr == "" { return 0 } // If time string is just time without date, use today's date if !strings.Contains(timeStr, "T") && !strings.Contains(timeStr, " ") { // Assume it's just a time like "15:04:05" today := time.Now().Format("2006-01-02") timeStr = fmt.Sprintf("%sT%s", today, timeStr) } if parsedTime, err := ParseDate(timeStr); err == nil { return parsedTime.Unix() } return 0 } func CalculateSubmissionDeadline(publicationDate time.Time) time.Time { deadline := publicationDate workingHoursAdded := 0 for workingHoursAdded < 48 { deadline = deadline.Add(1 * time.Hour) if deadline.Weekday() != time.Saturday && deadline.Weekday() != time.Sunday { workingHoursAdded++ } } return deadline } func CalculateApplicationDeadline(tenderDeadline time.Time) time.Time { applicationDeadline := tenderDeadline workingDaysSubtracted := 0 for workingDaysSubtracted < 7 { applicationDeadline = applicationDeadline.AddDate(0, 0, -1) if applicationDeadline.Weekday() != time.Saturday && applicationDeadline.Weekday() != time.Sunday { workingDaysSubtracted++ } } return applicationDeadline } // generateTenderURL generates the TED tender URL from NoticePublicationID func GenerateTenderURL(noticePublicationID string) string { if noticePublicationID == "" { return "" } // Remove leading zeros and format for URL // Example: 00522942-2025 -> https://ted.europa.eu/en/notice/-/detail/522942-2025 parts := strings.Split(noticePublicationID, "-") if len(parts) != 2 { return "" } // Convert to int and back to string to remove leading zeros if num, err := strconv.Atoi(parts[0]); err == nil { cleanID := fmt.Sprintf("%d-%s", num, parts[1]) return fmt.Sprintf("https://ted.europa.eu/en/notice/-/detail/%s", cleanID) } return "" }