diff --git a/docs/en-gb/_nav.json b/docs/en-gb/_nav.json index 399b846..c810b93 100644 --- a/docs/en-gb/_nav.json +++ b/docs/en-gb/_nav.json @@ -1,4 +1,9 @@ [ + { + "text": "projects", + "link": "/projects/", + "activeMatch": "/projects/" + }, { "text": "blogs", "link": "/blogs/", diff --git a/docs/en-gb/projects/calendar-toolbox/api.md b/docs/en-gb/projects/calendar-toolbox/api.md new file mode 100644 index 0000000..f1da780 --- /dev/null +++ b/docs/en-gb/projects/calendar-toolbox/api.md @@ -0,0 +1,390 @@ +--- +title: Calendar Toolbox API +--- + +## Package Overview + +The library is organised under the base package `com.onixbyte.calendar` with the following structure: + +| Package | Description | +|--------------------------------------------|--------------------------------------------| +| `com.onixbyte.calendar` | Root calendar object | +| `com.onixbyte.calendar.component` | iCalendar components (VEVENT, VTODO, etc.) | +| `com.onixbyte.calendar.component.property` | Component-level properties | +| `com.onixbyte.calendar.property` | Calendar-level properties | +| `com.onixbyte.calendar.parameter` | iCalendar property parameters | +| `com.onixbyte.calendar.recurrence` | Recurrence rule types | +| `com.onixbyte.calendar.value` | Value types | +| `com.onixbyte.calendar.util` | Formatting utilities | + +--- + +## Calendar + +The top-level object representing an iCalendar (RFC 5545) VCALENDAR container. + +```java +Calendar calendar = Calendar.builder() + .withCalendarScale(...) + .withMethod(...) + .withProductIdentifier(...) + .withVersion(...) + .withOwner(...) + .withPrimaryCalendar(...) + .withPublishedTTL(...) + .withCalendarDescription(...) + .withCalendarName(...) + .withCalendarId(...) + .withCustomProperties(...) + .withComponents(event, todo, ...) + .build(); + +String icsContent = calendar.formatted(); +``` + +### Calendar Properties + +All calendar-level properties live in `com.onixbyte.calendar.property` and implement `CalendarProperty`. + +| Class | iCalendar Property | Description | +|--------------------------|----------------------|-------------------------------------------| +| `CalendarScale` | `CALSCALE` | Calendar system (e.g., GREGORIAN) | +| `Method` | `METHOD` | iCalendar method (e.g., PUBLISH, REQUEST) | +| `ProductIdentifier` | `PRODID` | Product identifier of the calendar | +| `Version` | `VERSION` | iCalendar version (e.g., 2.0) | +| `Owner` | `X-OWNER` | Owner of the calendar | +| `PrimaryCalendar` | `X-PRIMARY-CALENDAR` | Whether this is a primary calendar | +| `PublishedTTL` | `X-PUBLISHED-TTL` | Time-to-live for published calendar | +| `CalendarDescription` | `X-CALENDAR-DESC` | Calendar description | +| `CalendarName` | `X-CALENDAR-NAME` | Calendar name | +| `CalendarId` | `X-CALENDAR-ID` | Calendar identifier | +| `CustomCalendarProperty` | `X-*` | Custom calendar properties | + +Custom properties are created using a builder: + +```java +var customProp = CustomCalendarProperty.builder() + .withParameters(...) + .build("X-MY-PROPERTY", "my-value"); +``` + +> Note: Custom property names **must** start with `X-`. + +--- + +## Components + +Components represent the core entities in an iCalendar object. Each component implements `CalendarComponent` and is rendered between `BEGIN:TYPE` and `END:TYPE` delimiters. + +### Event (VEVENT) + +Represents a scheduled event. + +```java +Event event = Event.builder() + .withDateTimeStamp(dtstamp) // required + .withUniqueIdentifier(uid) // required + .withDateTimeStart(dtstart) + .withDateTimeEnd(dtend) // mutually exclusive with duration + .withDuration(duration) // mutually exclusive with dtend + .withSummary(summary) + .withDescription(description) + .withClassification(classification) + .withDateTimeCreated(dateTimeCreated) + .withGeographicPosition(geoPos) + .withLastModified(lastModified) + .withLocation(location) + .withOrganiser(organiser) + .withPriority(priority) + .withSequenceNumber(seqNumber) + .withStatus(status) + .withTimeTransparency(transparency) + .withUniformResourceLocator(url) + .withRecurrenceId(recurrenceId) + .withRecurrenceRule(rrule) + .withAttachments(attachments) + .withAttendees(attendees) + .withCategories(categories) + .withComments(comments) + .withContacts(contacts) + .withExceptionDateTimes(exDates) + .withRequestStatuses(statuses) + .withRelated(related) + .withResources(resources) + .withRecurrenceDateTimes(rDates) + .build(); +``` + +### Todo (VTODO) + +Represents a to-do item or task. + +```java +Todo todo = Todo.builder() + .withDateTimeStamp(dtstamp) // required + .withUniqueIdentifier(uid) // required + .withSummary(summary) + .withDateTimeStart(dtstart) + .withDateTimeDue(due) // mutually exclusive with duration + .withDuration(duration) // mutually exclusive with due + .withDateTimeCompleted(completed) + .withPercentComplete(percent) + .withClassification(classification) + .withDateTimeCreated(created) + .withDescription(description) + .withGeographicPosition(geoPos) + .withLastModified(lastModified) + .withLocation(location) + .withOrganiser(organiser) + .withPriority(priority) + .withSequenceNumber(seq) + .withStatus(status) + .withRecurrenceId(recurId) + .withRecurrenceRule(rrule) + .withUniformResourceLocator(url) + .withAttachments(attachments) + .withAttendees(attendees) + .withCategories(categories) + .withComments(comments) + .withContacts(contacts) + .withExceptionDateTimes(exDates) + .withRequestStatuses(statuses) + .withRelatedToList(related) + .withResources(resources) + .withRecurrenceDateTimes(rDates) + .build(); +``` + +### Journal (VJOURNAL) + +Represents a journal entry or diary note. + +```java +Journal journal = Journal.builder() + .withDateTimeStamp(dtstamp) // required + .withUniqueIdentifier(uid) // required + .withSummary(summary) + .withClassification(classification) + .withDateTimeCreated(created) + .withDateTimeStart(dtstart) + .withLastModified(lastModified) + .withOrganiser(organiser) + .withRecurrenceId(recurId) + .withSequenceNumber(seq) + .withStatus(status) + .withUniformResourceLocator(url) + .withRecurrenceRule(rrule) + .withAttachments(attachments) + .withAttendees(attendees) + .withCategories(categories) + .withComments(comments) + .withContacts(contacts) + .withDescriptions(descriptions) + .withExceptionDateTimes(exDates) + .withRelatedToList(related) + .withRecurrenceDate(rDates) + .withRequestStatuses(statuses) + .build(); +``` + +### FreeBusy (VFREEBUSY) + +Represents free/busy time information. + +```java +FreeBusy freeBusy = FreeBusy.builder() + .withDateTimeStamp(dtstamp) // required + .withUniqueIdentifier(uid) // required + .withContact(contact) + .withDateTimeStart(dtstart) + .withDateTimeEnd(dtend) + .withOrganiser(organiser) + .withUniformResourceLocator(url) + .withAttendees(attendees) + .withComments(comments) + .withFreeBusyTimes(freeBusyTimes) + .withRequestStatuses(statuses) + .build(); +``` + +### TimeZone (VTIMEZONE) + +Defines time zone rules including standard and daylight saving time transitions. + +```java +TimeZone timezone = TimeZone.builder() + .withTimeZoneIdentifier(tzId) + .withLastModified(lastModified) + .withTimeZoneUrl(tzUrl) + .withTimeZoneProperties(standardProp, daylightProp) + .build(); +``` + +Time zone properties define the actual transition rules: + +```java +TimeZoneProperty standard = TimeZoneProperty.builder() + .withDateTimeStart(dtstart) + .withTimeZoneOffsetTo(offsetTo) + .withTimeZoneOffsetFrom(offsetFrom) + .withRecurrenceRule(rrule) + .withTimeZoneNames(tzName) + .buildStandard(); // or buildDaylight() + +TimeZoneProperty daylight = TimeZoneProperty.builder() + .withDateTimeStart(dtstart) + .withTimeZoneOffsetTo(offsetTo) + .withTimeZoneOffsetFrom(offsetFrom) + .buildDaylight(); +``` + +### Alarm (VALARM) + +Defines alarm/reminder notifications. Three alarm types are supported: + +```java +// Audio alarm +Alarm audioAlarm = Alarm.builder() + .withTrigger(trigger) + .withDuration(duration) + .withRepeatCount(repeatCount) + .withAttachments(audioAttachment) + .buildAudio(); + +// Display alarm +Alarm displayAlarm = Alarm.builder() + .withTrigger(trigger) + .withDescription(description) // required + .withDuration(duration) + .withRepeatCount(repeatCount) + .buildDisplay(); + +// Email alarm +Alarm emailAlarm = Alarm.builder() + .withTrigger(trigger) + .withDescription(description) // required + .withSummary(summary) // required + .withAttendees(attendees) // required + .withDuration(duration) + .withRepeatCount(repeatCount) + .buildEmail(); +``` + +--- + +## Component Properties + +Component properties live in `com.onixbyte.calendar.component.property` and implement `ComponentProperty`. + +| Class | iCalendar Property | Description | +|---------------------------|--------------------|----------------------------------------------------------| +| `Action` | `ACTION` | Alarm action type (AUDIO, DISPLAY, EMAIL) | +| `Attachment` | `ATTACH` | Document attachment | +| `Attendee` | `ATTENDEE` | Event/task attendee | +| `Categories` | `CATEGORIES` | Categories or tags | +| `Classification` | `CLASS` | Access classification (PUBLIC, PRIVATE, CONFIDENTIAL) | +| `Comment` | `COMMENT` | Comment | +| `Contact` | `CONTACT` | Contact information | +| `DateTimeCompleted` | `COMPLETED` | Completion date-time | +| `DateTimeCreated` | `CREATED` | Creation date-time | +| `DateTimeDue` | `DUE` | Due date-time | +| `DateTimeEnd` | `DTEND` | End date-time | +| `DateTimeStamp` | `DTSTAMP` | Date-time stamp | +| `DateTimeStart` | `DTSTART` | Start date-time | +| `Description` | `DESCRIPTION` | Description | +| `ExceptionDateTimes` | `EXDATE` | Exception date-times | +| `FreeBusyTime` | `FREEBUSY` | Free/busy time periods | +| `GeographicPosition` | `GEO` | Geographic position (lat/long) | +| `LastModified` | `LAST-MODIFIED` | Last modified date-time | +| `Location` | `LOCATION` | Location | +| `Organiser` | `ORGANIZER` | Event organiser | +| `PercentComplete` | `PERCENT-COMPLETE` | Completion percentage | +| `Priority` | `PRIORITY` | Priority level | +| `RecurrenceDateTimes` | `RDATE` | Recurrence date-times | +| `RecurrenceId` | `RECURRENCE-ID` | Recurrence instance identifier | +| `RecurrenceRule` | `RRULE` | Recurrence rule | +| `RelatedTo` | `RELATED-TO` | Related component reference | +| `RepeatCount` | `REPEAT` | Alarm repeat count | +| `RequestStatus` | `REQUEST-STATUS` | Request status | +| `Resources` | `RESOURCES` | Resources | +| `SequenceNumber` | `SEQUENCE` | Sequence number (revision) | +| `Status` | `STATUS` | Component status (TENTATIVE, CONFIRMED, CANCELLED, etc.) | +| `Summary` | `SUMMARY` | Title or summary | +| `TimeTransparency` | `TRANSP` | Time transparency (OPAQUE, TRANSPARENT) | +| `TimeZoneIdentifier` | `TZID` | Time zone identifier | +| `TimeZoneName` | `TZNAME` | Time zone name | +| `TimeZoneOffsetFrom` | `TZOFFSETFROM` | Time zone offset from UTC | +| `TimeZoneOffsetTo` | `TZOFFSETTO` | Time zone offset to UTC | +| `TimeZoneUrl` | `TZURL` | Time zone URL | +| `Trigger` | `TRIGGER` | Alarm trigger | +| `UniformResourceLocator` | `URL` | Associated URL | +| `UniqueIdentifier` | `UID` | Unique identifier | +| `CustomComponentProperty` | `X-*` | Custom component properties | + +--- + +## Parameters + +Parameters in `com.onixbyte.calendar.parameter` provide additional qualifiers on component properties. + +| Class | iCalendar Parameter | Description | +|-------------------------------|---------------------|--------------------------------------------------------| +| `AlarmTriggerRelationship` | `RELATED` | Trigger relationship (START, END) | +| `AlternateTextRepresentation` | `ALTREP` | Alternate text URI | +| `CalendarUserType` | `CUTYPE` | Calendar user type (INDIVIDUAL, GROUP, RESOURCE, etc.) | +| `CommonName` | `CN` | Common name | +| `Delegatees` | `DELEGATED-TO` | Delegatees | +| `Delegators` | `DELEGATED-FROM` | Delegators | +| `DirectoryEntryReference` | `DIR` | Directory entry URI | +| `FormatType` | `FMTTYPE` | Format type (MIME type) | +| `FreeBusyTimeType` | `FBTYPE` | Free/busy time type | +| `InlineEncoding` | `ENCODING` | Inline encoding (BASE64) | +| `Language` | `LANGUAGE` | Language | +| `Membership` | `MEMBER` | Group membership | +| `ParticipationRole` | `ROLE` | Participation role (CHAIR, REQ-PARTICIPANT, etc.) | +| `ParticipationStatus` | `PARTSTAT` | Participation status (ACCEPTED, DECLINED, etc.) | +| `RecurrenceIdentifierRange` | `RANGE` | Recurrence range (THISANDPRIOR, THISANDFUTURE) | +| `RelationshipType` | `RELTYPE` | Relationship type (PARENT, CHILD, SIBLING) | +| `RsvpExpectation` | `RSVP` | RSVP expectation (TRUE, FALSE) | +| `SentBy` | `SENT-BY` | Sent by | +| `TimeZoneIdentifier` | `TZID` | Time zone identifier | +| `ValueDataType` | `VALUE` | Value data type (DATE, DATE-TIME, etc.) | + +--- + +## Recurrence Types + +Located in `com.onixbyte.calendar.recurrence`. + +| Class | Description | +|--------------|---------------------------------------------------------------------------| +| `Frequency` | Frequency constants (DAILY, WEEKLY, MONTHLY, YEARLY) for recurrence rules | +| `WeekdayNum` | Weekday number for recurrence rules (e.g., 2nd Monday) | + +--- + +## Value Types + +Located in `com.onixbyte.calendar.value`. + +| Class | Description | +|---------------------|------------------------------------------------| +| `FreeBusyTimeValue` | Represents free/busy time value | +| `PeriodOfTime` | Represents a period of time with start and end | +| `PropertyValue` | Base value type for properties | +| `UtcOffset` | UTC offset value (e.g., `-05:00`, `+01:00`) | + +--- + +## Formatted Output + +All components and properties provide a `formatted()` method that returns an iCalendar-compliant string representation. The `Calendar.formatted()` method produces a complete `.ics` output wrapped in `BEGIN:VCALENDAR`/`END:VCALENDAR`. + +```java +String ics = calendar.formatted(); +// BEGIN:VCALENDAR +// CALSCALE:GREGORIAN +// METHOD:PUBLISH +// ... +// END:VCALENDAR +``` diff --git a/docs/en-gb/projects/calendar-toolbox/index.mdx b/docs/en-gb/projects/calendar-toolbox/index.mdx new file mode 100644 index 0000000..b878f9d --- /dev/null +++ b/docs/en-gb/projects/calendar-toolbox/index.mdx @@ -0,0 +1,109 @@ +--- +title: Calendar Toolbox +--- + +import { Tabs, Tab } from "@rspress/core/theme" + +## Introduction + +Calendar Toolbox is a Java library designed to simplify the creation of `.ics` files, adhering to the iCalendar specification (RFC 5545). This library provides developers with a straightforward API to generate calendar events that can be imported into popular calendar applications such as Microsoft Outlook, Google Calendar, and Apple Calendar. + +With Calendar Toolbox, you can effortlessly create, customise, and export calendar event files programmatically, enabling integration of calendar functionalities into your Java applications with minimal effort. + +## Features + +- **Full RFC 5545 Compliance** — Supports standard iCalendar components including VEVENT, VTODO, VJOURNAL, VFREEBUSY, VTIMEZONE, and VALARM. +- **Fluent Builder Pattern** — All components and properties use builder pattern for readable and intuitive construction. +- **Type-Safe Properties** — Strongly typed properties and parameters ensure correctness at compile time. +- **Custom Extensions** — Support for custom `X-` properties at both calendar and component level. +- **Lightweight** — Zero external dependencies for core functionality. + +## Installation + + + + ```groovy title="build.gradle" + dependencies { + implementation 'com.onixbyte:calendar-toolbox:1.1.0' + } + ``` + + + ```kotlin title="build.gradle.kts" + dependencies { + implementation("com.onixbyte:calendar-toolbox:1.1.0") + } + ``` + + + ```xml title="pom.xml" + + + com.onixbyte + calendar-toolbox + 1.1.0 + + + ``` + + + +## Quick Start + +```java +import com.onixbyte.calendar.Calendar; +import com.onixbyte.calendar.component.Event; +import com.onixbyte.calendar.component.property.*; +import com.onixbyte.calendar.property.*; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; + +public class CalendarExample { + + public static void main(String[] args) { + // Create required date-time properties + var now = ZonedDateTime.now(ZoneOffset.UTC); + var dtstamp = DateTimeStamp.of(now); + var uid = UniqueIdentifier.of("meeting-001@example.com"); + var dtstart = DateTimeStart.of( + LocalDateTime.of(2025, 8, 15, 9, 0), + "America/New_York" + ); + var dtend = DateTimeEnd.of( + LocalDateTime.of(2025, 8, 15, 10, 0), + "America/New_York" + ); + var summary = Summary.of("Team Standup"); + var description = Description.of("Daily team standup meeting."); + + // Build the event + var event = Event.builder() + .withDateTimeStamp(dtstamp) + .withUniqueIdentifier(uid) + .withDateTimeStart(dtstart) + .withDateTimeEnd(dtend) + .withSummary(summary) + .withDescription(description) + .build(); + + // Build the calendar and output .ics content + var calendar = Calendar.builder() + .withCalendarScale(CalendarScale.of("GREGORIAN")) + .withMethod(Method.of("PUBLISH")) + .withProductIdentifier(ProductIdentifier.of("-//OnixByte//Calendar Toolbox//EN")) + .withVersion(Version.of("2.0")) + .withComponents(event) + .build(); + + System.out.println(calendar.formatted()); + } +} +``` + +This produces an `.ics` string that can be saved to a file or sent via email. + +## License + +Calendar Toolbox is open-source software released under the MIT License. diff --git a/docs/en-gb/projects/index.md b/docs/en-gb/projects/index.md new file mode 100644 index 0000000..32ed832 --- /dev/null +++ b/docs/en-gb/projects/index.md @@ -0,0 +1,5 @@ +--- +title: Projects +--- + +Explore awesome projects developed by OnixByte. \ No newline at end of file diff --git a/docs/zh-hans/_nav.json b/docs/zh-hans/_nav.json index 399b846..c810b93 100644 --- a/docs/zh-hans/_nav.json +++ b/docs/zh-hans/_nav.json @@ -1,4 +1,9 @@ [ + { + "text": "projects", + "link": "/projects/", + "activeMatch": "/projects/" + }, { "text": "blogs", "link": "/blogs/", diff --git a/docs/zh-hans/projects/calendar-toolbox/api.md b/docs/zh-hans/projects/calendar-toolbox/api.md new file mode 100644 index 0000000..76184d0 --- /dev/null +++ b/docs/zh-hans/projects/calendar-toolbox/api.md @@ -0,0 +1,390 @@ +--- +title: Calendar Toolbox API +--- + +## 包结构概览 + +库的代码组织在基础包 `com.onixbyte.calendar` 下,结构如下: + +| 包 | 描述 | +|---|---| +| `com.onixbyte.calendar` | 根日历对象 | +| `com.onixbyte.calendar.component` | iCalendar 组件(VEVENT、VTODO 等) | +| `com.onixbyte.calendar.component.property` | 组件级属性 | +| `com.onixbyte.calendar.property` | 日历级属性 | +| `com.onixbyte.calendar.parameter` | iCalendar 属性参数 | +| `com.onixbyte.calendar.recurrence` | 重复规则类型 | +| `com.onixbyte.calendar.value` | 值类型 | +| `com.onixbyte.calendar.util` | 格式化工具类 | + +--- + +## Calendar + +表示 iCalendar(RFC 5545)VCALENDAR 容器的顶层对象。 + +```java +Calendar calendar = Calendar.builder() + .withCalendarScale(...) + .withMethod(...) + .withProductIdentifier(...) + .withVersion(...) + .withOwner(...) + .withPrimaryCalendar(...) + .withPublishedTTL(...) + .withCalendarDescription(...) + .withCalendarName(...) + .withCalendarId(...) + .withCustomProperties(...) + .withComponents(event, todo, ...) + .build(); + +String icsContent = calendar.formatted(); +``` + +### 日历属性 + +所有日历级属性位于 `com.onixbyte.calendar.property`,实现 `CalendarProperty` 接口。 + +| 类 | iCalendar 属性 | 描述 | +|---|---|---| +| `CalendarScale` | `CALSCALE` | 日历系统(例如 GREGORIAN) | +| `Method` | `METHOD` | iCalendar 方法(例如 PUBLISH、REQUEST) | +| `ProductIdentifier` | `PRODID` | 日历的产品标识符 | +| `Version` | `VERSION` | iCalendar 版本(例如 2.0) | +| `Owner` | `X-OWNER` | 日历所有者 | +| `PrimaryCalendar` | `X-PRIMARY-CALENDAR` | 是否为主日历 | +| `PublishedTTL` | `X-PUBLISHED-TTL` | 已发布日历的生存时间 | +| `CalendarDescription` | `X-CALENDAR-DESC` | 日历描述 | +| `CalendarName` | `X-CALENDAR-NAME` | 日历名称 | +| `CalendarId` | `X-CALENDAR-ID` | 日历标识符 | +| `CustomCalendarProperty` | `X-*` | 自定义日历属性 | + +自定义属性使用 Builder 创建: + +```java +var customProp = CustomCalendarProperty.builder() + .withParameters(...) + .build("X-MY-PROPERTY", "my-value"); +``` + +> 注意:自定义属性名称**必须**以 `X-` 开头。 + +--- + +## 组件 + +组件是 iCalendar 对象的核心实体。每个组件实现 `CalendarComponent` 接口,并在 `BEGIN:TYPE` 和 `END:TYPE` 定界符之间渲染。 + +### Event(VEVENT) + +表示一个预定的活动/事件。 + +```java +Event event = Event.builder() + .withDateTimeStamp(dtstamp) // 必需 + .withUniqueIdentifier(uid) // 必需 + .withDateTimeStart(dtstart) + .withDateTimeEnd(dtend) // 与 duration 互斥 + .withDuration(duration) // 与 dtend 互斥 + .withSummary(summary) + .withDescription(description) + .withClassification(classification) + .withDateTimeCreated(dateTimeCreated) + .withGeographicPosition(geoPos) + .withLastModified(lastModified) + .withLocation(location) + .withOrganiser(organiser) + .withPriority(priority) + .withSequenceNumber(seqNumber) + .withStatus(status) + .withTimeTransparency(transparency) + .withUniformResourceLocator(url) + .withRecurrenceId(recurrenceId) + .withRecurrenceRule(rrule) + .withAttachments(attachments) + .withAttendees(attendees) + .withCategories(categories) + .withComments(comments) + .withContacts(contacts) + .withExceptionDateTimes(exDates) + .withRequestStatuses(statuses) + .withRelated(related) + .withResources(resources) + .withRecurrenceDateTimes(rDates) + .build(); +``` + +### Todo(VTODO) + +表示待办事项或任务。 + +```java +Todo todo = Todo.builder() + .withDateTimeStamp(dtstamp) // 必需 + .withUniqueIdentifier(uid) // 必需 + .withSummary(summary) + .withDateTimeStart(dtstart) + .withDateTimeDue(due) // 与 duration 互斥 + .withDuration(duration) // 与 due 互斥 + .withDateTimeCompleted(completed) + .withPercentComplete(percent) + .withClassification(classification) + .withDateTimeCreated(created) + .withDescription(description) + .withGeographicPosition(geoPos) + .withLastModified(lastModified) + .withLocation(location) + .withOrganiser(organiser) + .withPriority(priority) + .withSequenceNumber(seq) + .withStatus(status) + .withRecurrenceId(recurId) + .withRecurrenceRule(rrule) + .withUniformResourceLocator(url) + .withAttachments(attachments) + .withAttendees(attendees) + .withCategories(categories) + .withComments(comments) + .withContacts(contacts) + .withExceptionDateTimes(exDates) + .withRequestStatuses(statuses) + .withRelatedToList(related) + .withResources(resources) + .withRecurrenceDateTimes(rDates) + .build(); +``` + +### Journal(VJOURNAL) + +表示日记条目或笔记。 + +```java +Journal journal = Journal.builder() + .withDateTimeStamp(dtstamp) // 必需 + .withUniqueIdentifier(uid) // 必需 + .withSummary(summary) + .withClassification(classification) + .withDateTimeCreated(created) + .withDateTimeStart(dtstart) + .withLastModified(lastModified) + .withOrganiser(organiser) + .withRecurrenceId(recurId) + .withSequenceNumber(seq) + .withStatus(status) + .withUniformResourceLocator(url) + .withRecurrenceRule(rrule) + .withAttachments(attachments) + .withAttendees(attendees) + .withCategories(categories) + .withComments(comments) + .withContacts(contacts) + .withDescriptions(descriptions) + .withExceptionDateTimes(exDates) + .withRelatedToList(related) + .withRecurrenceDate(rDates) + .withRequestStatuses(statuses) + .build(); +``` + +### FreeBusy(VFREEBUSY) + +表示空闲/忙碌时间信息。 + +```java +FreeBusy freeBusy = FreeBusy.builder() + .withDateTimeStamp(dtstamp) // 必需 + .withUniqueIdentifier(uid) // 必需 + .withContact(contact) + .withDateTimeStart(dtstart) + .withDateTimeEnd(dtend) + .withOrganiser(organiser) + .withUniformResourceLocator(url) + .withAttendees(attendees) + .withComments(comments) + .withFreeBusyTimes(freeBusyTimes) + .withRequestStatuses(statuses) + .build(); +``` + +### TimeZone(VTIMEZONE) + +定义时区规则,包括标准时间和夏令时转换。 + +```java +TimeZone timezone = TimeZone.builder() + .withTimeZoneIdentifier(tzId) + .withLastModified(lastModified) + .withTimeZoneUrl(tzUrl) + .withTimeZoneProperties(standardProp, daylightProp) + .build(); +``` + +时区属性定义实际的转换规则: + +```java +TimeZoneProperty standard = TimeZoneProperty.builder() + .withDateTimeStart(dtstart) + .withTimeZoneOffsetTo(offsetTo) + .withTimeZoneOffsetFrom(offsetFrom) + .withRecurrenceRule(rrule) + .withTimeZoneNames(tzName) + .buildStandard(); // 或 buildDaylight() + +TimeZoneProperty daylight = TimeZoneProperty.builder() + .withDateTimeStart(dtstart) + .withTimeZoneOffsetTo(offsetTo) + .withTimeZoneOffsetFrom(offsetFrom) + .buildDaylight(); +``` + +### Alarm(VALARM) + +定义闹钟/提醒通知。支持三种闹钟类型: + +```java +// 音频闹钟 +Alarm audioAlarm = Alarm.builder() + .withTrigger(trigger) + .withDuration(duration) + .withRepeatCount(repeatCount) + .withAttachments(audioAttachment) + .buildAudio(); + +// 显示闹钟 +Alarm displayAlarm = Alarm.builder() + .withTrigger(trigger) + .withDescription(description) // 必需 + .withDuration(duration) + .withRepeatCount(repeatCount) + .buildDisplay(); + +// 邮件闹钟 +Alarm emailAlarm = Alarm.builder() + .withTrigger(trigger) + .withDescription(description) // 必需 + .withSummary(summary) // 必需 + .withAttendees(attendees) // 必需 + .withDuration(duration) + .withRepeatCount(repeatCount) + .buildEmail(); +``` + +--- + +## 组件属性 + +组件属性位于 `com.onixbyte.calendar.component.property`,实现 `ComponentProperty` 接口。 + +| 类 | iCalendar 属性 | 描述 | +|---|---|---| +| `Action` | `ACTION` | 闹钟操作类型(AUDIO、DISPLAY、EMAIL) | +| `Attachment` | `ATTACH` | 文档附件 | +| `Attendee` | `ATTENDEE` | 事件/任务参与者 | +| `Categories` | `CATEGORIES` | 类别或标签 | +| `Classification` | `CLASS` | 访问分类(PUBLIC、PRIVATE、CONFIDENTIAL) | +| `Comment` | `COMMENT` | 评论 | +| `Contact` | `CONTACT` | 联系信息 | +| `DateTimeCompleted` | `COMPLETED` | 完成日期时间 | +| `DateTimeCreated` | `CREATED` | 创建日期时间 | +| `DateTimeDue` | `DUE` | 截止日期时间 | +| `DateTimeEnd` | `DTEND` | 结束日期时间 | +| `DateTimeStamp` | `DTSTAMP` | 日期时间戳 | +| `DateTimeStart` | `DTSTART` | 开始日期时间 | +| `Description` | `DESCRIPTION` | 描述 | +| `ExceptionDateTimes` | `EXDATE` | 例外日期时间 | +| `FreeBusyTime` | `FREEBUSY` | 空闲/忙碌时间段 | +| `GeographicPosition` | `GEO` | 地理位置(纬度/经度) | +| `LastModified` | `LAST-MODIFIED` | 最后修改日期时间 | +| `Location` | `LOCATION` | 地点 | +| `Organiser` | `ORGANIZER` | 组织者 | +| `PercentComplete` | `PERCENT-COMPLETE` | 完成百分比 | +| `Priority` | `PRIORITY` | 优先级 | +| `RecurrenceDateTimes` | `RDATE` | 重复日期时间 | +| `RecurrenceId` | `RECURRENCE-ID` | 重复实例标识符 | +| `RecurrenceRule` | `RRULE` | 重复规则 | +| `RelatedTo` | `RELATED-TO` | 相关组件引用 | +| `RepeatCount` | `REPEAT` | 闹钟重复次数 | +| `RequestStatus` | `REQUEST-STATUS` | 请求状态 | +| `Resources` | `RESOURCES` | 资源 | +| `SequenceNumber` | `SEQUENCE` | 序列号(修订版本) | +| `Status` | `STATUS` | 组件状态(TENTATIVE、CONFIRMED、CANCELLED 等) | +| `Summary` | `SUMMARY` | 标题或摘要 | +| `TimeTransparency` | `TRANSP` | 时间透明度(OPAQUE、TRANSPARENT) | +| `TimeZoneIdentifier` | `TZID` | 时区标识符 | +| `TimeZoneName` | `TZNAME` | 时区名称 | +| `TimeZoneOffsetFrom` | `TZOFFSETFROM` | 相对于 UTC 的时区偏移(原) | +| `TimeZoneOffsetTo` | `TZOFFSETTO` | 相对于 UTC 的时区偏移(目标) | +| `TimeZoneUrl` | `TZURL` | 时区 URL | +| `Trigger` | `TRIGGER` | 闹钟触发器 | +| `UniformResourceLocator` | `URL` | 关联 URL | +| `UniqueIdentifier` | `UID` | 唯一标识符 | +| `CustomComponentProperty` | `X-*` | 自定义组件属性 | + +--- + +## 参数 + +参数位于 `com.onixbyte.calendar.parameter`,为组件属性提供额外限定。 + +| 类 | iCalendar 参数 | 描述 | +|---|---|---| +| `AlarmTriggerRelationship` | `RELATED` | 触发器关联(START、END) | +| `AlternateTextRepresentation` | `ALTREP` | 替代文本 URI | +| `CalendarUserType` | `CUTYPE` | 日历用户类型(INDIVIDUAL、GROUP、RESOURCE 等) | +| `CommonName` | `CN` | 通用名称 | +| `Delegatees` | `DELEGATED-TO` | 受托人 | +| `Delegators` | `DELEGATED-FROM` | 委托人 | +| `DirectoryEntryReference` | `DIR` | 目录条目 URI | +| `FormatType` | `FMTTYPE` | 格式类型(MIME 类型) | +| `FreeBusyTimeType` | `FBTYPE` | 空闲/忙碌时间类型 | +| `InlineEncoding` | `ENCODING` | 内联编码(BASE64) | +| `Language` | `LANGUAGE` | 语言 | +| `Membership` | `MEMBER` | 组成员 | +| `ParticipationRole` | `ROLE` | 参与角色(CHAIR、REQ-PARTICIPANT 等) | +| `ParticipationStatus` | `PARTSTAT` | 参与状态(ACCEPTED、DECLINED 等) | +| `RecurrenceIdentifierRange` | `RANGE` | 重复范围(THISANDPRIOR、THISANDFUTURE) | +| `RelationshipType` | `RELTYPE` | 关系类型(PARENT、CHILD、SIBLING) | +| `RsvpExpectation` | `RSVP` | RSVP 期望(TRUE、FALSE) | +| `SentBy` | `SENT-BY` | 发送者 | +| `TimeZoneIdentifier` | `TZID` | 时区标识符 | +| `ValueDataType` | `VALUE` | 值数据类型(DATE、DATE-TIME 等) | + +--- + +## 递归类型 + +位于 `com.onixbyte.calendar.recurrence`。 + +| 类 | 描述 | +|---|---| +| `Frequency` | 重复频率常量(DAILY、WEEKLY、MONTHLY、YEARLY),用于重复规则 | +| `WeekdayNum` | 重复规则的星期序号(例如第 2 个星期一) | + +--- + +## 值类型 + +位于 `com.onixbyte.calendar.value`。 + +| 类 | 描述 | +|---|---| +| `FreeBusyTimeValue` | 表示空闲/忙碌时间值 | +| `PeriodOfTime` | 表示一个时间段,包含开始和结束 | +| `PropertyValue` | 属性的基础值类型 | +| `UtcOffset` | UTC 偏移值(例如 `-05:00`、`+01:00`) | + +--- + +## 格式化输出 + +所有组件和属性都提供 `formatted()` 方法,返回符合 iCalendar 规范的字符串。`Calendar.formatted()` 方法生成完整的 `.ics` 输出,包含 `BEGIN:VCALENDAR`/`END:VCALENDAR`。 + +```java +String ics = calendar.formatted(); +// BEGIN:VCALENDAR +// CALSCALE:GREGORIAN +// METHOD:PUBLISH +// ... +// END:VCALENDAR +``` diff --git a/docs/zh-hans/projects/calendar-toolbox/index.mdx b/docs/zh-hans/projects/calendar-toolbox/index.mdx new file mode 100644 index 0000000..fde362d --- /dev/null +++ b/docs/zh-hans/projects/calendar-toolbox/index.mdx @@ -0,0 +1,109 @@ +--- +title: Calendar Toolbox +--- + +import { Tabs, Tab } from "@rspress/core/theme" + +## 介绍 + +Calendar Toolbox 是一个 Java 库,旨在简化遵循 iCalendar 规范(RFC 5545)的 `.ics` 文件的创建。该库为开发者提供了简洁的 API,可生成能够导入到 Microsoft Outlook、Google Calendar 和 Apple Calendar 等主流日历应用程序中的日历事件。 + +通过 Calendar Toolbox,您可以以编程方式轻松创建、定制和导出日历事件文件,从而以最少的代价将日历功能集成到您的 Java 应用中。 + +## 特性 + +- **完整 RFC 5545 兼容** — 支持 VEVENT、VTODO、VJOURNAL、VFREEBUSY、VTIMEZONE 和 VALARM 等标准 iCalendar 组件。 +- **流式 Builder 模式** — 所有组件和属性均使用 Builder 模式,构建过程可读性强且直观。 +- **类型安全属性** — 强类型的属性和参数确保编译期正确性。 +- **自定义扩展** — 支持日历级和组件级的自定义 `X-` 属性。 +- **轻量级** — 核心功能零外部依赖。 + +## 安装 + + + + ```groovy title="build.gradle" + dependencies { + implementation 'com.onixbyte:calendar-toolbox:1.1.0' + } + ``` + + + ```kotlin title="build.gradle.kts" + dependencies { + implementation("com.onixbyte:calendar-toolbox:1.1.0") + } + ``` + + + ```xml title="pom.xml" + + + com.onixbyte + calendar-toolbox + 1.1.0 + + + ``` + + + +## 快速开始 + +```java +import com.onixbyte.calendar.Calendar; +import com.onixbyte.calendar.component.Event; +import com.onixbyte.calendar.component.property.*; +import com.onixbyte.calendar.property.*; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; + +public class CalendarExample { + + public static void main(String[] args) { + // 创建所需的日期时间属性 + var now = ZonedDateTime.now(ZoneOffset.UTC); + var dtstamp = DateTimeStamp.of(now); + var uid = UniqueIdentifier.of("meeting-001@example.com"); + var dtstart = DateTimeStart.of( + LocalDateTime.of(2025, 8, 15, 9, 0), + "America/New_York" + ); + var dtend = DateTimeEnd.of( + LocalDateTime.of(2025, 8, 15, 10, 0), + "America/New_York" + ); + var summary = Summary.of("Team Standup"); + var description = Description.of("Daily team standup meeting."); + + // 构建事件 + var event = Event.builder() + .withDateTimeStamp(dtstamp) + .withUniqueIdentifier(uid) + .withDateTimeStart(dtstart) + .withDateTimeEnd(dtend) + .withSummary(summary) + .withDescription(description) + .build(); + + // 构建日历并输出 .ics 内容 + var calendar = Calendar.builder() + .withCalendarScale(CalendarScale.of("GREGORIAN")) + .withMethod(Method.of("PUBLISH")) + .withProductIdentifier(ProductIdentifier.of("-//OnixByte//Calendar Toolbox//EN")) + .withVersion(Version.of("2.0")) + .withComponents(event) + .build(); + + System.out.println(calendar.formatted()); + } +} +``` + +上述代码会生成一个 `.ics` 格式的字符串,可以保存为文件或通过邮件发送。 + +## 许可证 + +Calendar Toolbox 是采用 MIT 许可证发布的开源软件。 diff --git a/docs/zh-hans/projects/index.md b/docs/zh-hans/projects/index.md new file mode 100644 index 0000000..de4ab44 --- /dev/null +++ b/docs/zh-hans/projects/index.md @@ -0,0 +1,5 @@ +--- +title: 项目 +--- + +探索由 OnixByte 开发的开源项目。 \ No newline at end of file diff --git a/i18n.json b/i18n.json index 949eb2f..de46ba9 100644 --- a/i18n.json +++ b/i18n.json @@ -118,5 +118,9 @@ "notifications": { "en-gb": "Notifications", "zh-hans": "通知" + }, + "projects": { + "en-gb": "Projects", + "zh-hans": "项目" } }