InternetCalendarSubscriptionService.java
package com.tdmconsult.ete.ical;
import com.tdmconsult.ete.services.yahoo.YahooFinanceService;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.info.BuildProperties;
import org.springframework.boot.info.GitProperties;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class InternetCalendarSubscriptionService {
private static final DateTimeFormatter DATE_TIME =
DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'")
.withZone(ZoneOffset.UTC);
public static final String CRLF = "\r\n";
private final YahooFinanceService yahooFinanceService;
@Autowired
private Optional<GitProperties> gitProperties;
@Autowired
private Optional<BuildProperties> buildProperties;
public String getEarningsCalendar() {
final var events = yahooFinanceService.getUpcomingEarningsEvents();
final var sb = new StringBuilder(8192);
sb.append("BEGIN:VCALENDAR").append(CRLF);
sb.append("VERSION:2.0").append(CRLF);
sb.append("PRODID:-//TDM Consult GmbH//ETE 0.0.0//EN").append(CRLF);
sb.append("CALSCALE:GREGORIAN").append(CRLF);
sb.append("METHOD:PUBLISH").append(CRLF);
sb.append("X-WR-CALNAME:Earnings Calendar").append(CRLF);
buildProperties.ifPresent(properties -> {
sb.append("X-APP-VERSION:").append(properties.getVersion()).append(CRLF);
});
gitProperties.ifPresent(properties -> {
sb.append("X-GIT-COMMIT:").append(properties.getShortCommitId()).append(CRLF);
});
for (var event : events) {
final var security = event.security();
sb.append("BEGIN:VEVENT\r\n");
sb.append("UID:")
.append(event.publicId())
.append("@earnings")
.append(CRLF);
sb.append("SEQUENCE:")
.append(event.version())
.append(CRLF);
sb.append("LAST-MODIFIED:")
.append(event.updatedAt()
.atOffset(ZoneOffset.UTC)
.format(DATE_TIME))
.append(CRLF);
sb.append("DTSTAMP:")
.append(event.createdAt()
.atOffset(ZoneOffset.UTC)
.format(DATE_TIME))
.append(CRLF);
sb.append("DTSTART;VALUE=DATE:")
.append(event.earningsDate().format(DateTimeFormatter.BASIC_ISO_DATE))
.append(CRLF);
sb.append("SUMMARY:")
.append(escape(security.name()))
.append(" Earnings")
.append(CRLF);
sb.append("DESCRIPTION:")
.append("ISIN: ")
.append(security.isin())
.append("\\n")
.append(event.isConfirmed() ? "Confirmed" : "Preliminary")
.append(CRLF);
sb.append("STATUS:")
.append(event.isConfirmed() ? "CONFIRMED" : "TENTATIVE")
.append(CRLF);
sb.append("TRANSP:TRANSPARENT\r\n");
sb.append("END:VEVENT\r\n");
}
sb.append("END:VCALENDAR\r\n");
return sb.toString();
}
private static String escape(final String value) {
if (value == null) {
return "";
}
return value
.replace("\\", "\\\\")
.replace(";", "\\;")
.replace(",", "\\,")
.replace("\r", "")
.replace("\n", "\\n");
}
}