Skip to content

KashCal/parsely

Repository files navigation

Parsely

Natural language date/time parser for Kotlin/JVM. Zero dependencies.

val result = QuickAddParser.parse("Coffee with Sarah tomorrow at 3pm at Starbucks")

result.title      // "Coffee with Sarah"
result.startDate  // 2026-04-17
result.startTime  // 15:00
result.location   // "Starbucks"
result.emoji      // "☕"
result.confidence // HIGH

Installation

Gradle (Kotlin DSL)

repositories {
    maven {
        url = uri("https://maven.pkg.github.com/KashCal/parsely")
        credentials {
            username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR")
            password = project.findProperty("gpr.key") as String? ?: System.getenv("GITHUB_TOKEN")
        }
    }
}

dependencies {
    implementation("org.onekash.parsely:parsely:0.1.0")
}

Gradle (Groovy)

repositories {
    maven {
        url = uri("https://maven.pkg.github.com/KashCal/parsely")
        credentials {
            username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR")
            password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
        }
    }
}

dependencies {
    implementation 'org.onekash.parsely:parsely:0.1.0'
}

Note: GitHub Packages requires authentication. Add gpr.user and gpr.key (a personal access token with read:packages scope) to your ~/.gradle/gradle.properties.

Examples

import org.onekash.parsely.QuickAddParser

// Dates and times
QuickAddParser.parse("Dentist Jan 15 at 2pm")
// title="Dentist", startDate=Jan 15, startTime=14:00

// Time ranges
QuickAddParser.parse("Team standup 9-10am")
// startTime=09:00, endTime=10:00

// Durations
QuickAddParser.parse("Workshop tomorrow for 2 hours")
// endTime = startTime + 2h

// Recurrence
QuickAddParser.parse("Yoga every Monday")
// rrule="FREQ=WEEKLY;BYDAY=MO"

// Locations (last "at" phrase after time)
QuickAddParser.parse("Dinner Friday at 7pm at The Italian Place")
// location="The Italian Place"

// Relative offsets
QuickAddParser.parse("Follow up in 3 days")
// startDate = today + 3

// Structured dates
QuickAddParser.parse("Report due 2026-01-15")
// startDate=2026-01-15

Reference Date

Parsing resolves relative dates against LocalDateTime.now(). For testing, pass a fixed reference:

val ref = LocalDateTime.of(2026, 1, 15, 9, 0)
val result = QuickAddParser.parse("Meeting next Friday at 2pm", reference = ref)
// startDate=2026-01-23, startTime=14:00

QuickAddResult

Field Type Description
title String Extracted event title (remaining text after parsing)
startDate LocalDate Parsed date, or today if none found
startTime LocalTime? Parsed time, or null for all-day
endTime LocalTime? End time from range or duration
location String? Location from trailing "at" phrase
rrule String? RFC 5545 RRULE string
emoji String? Matched emoji based on title keywords
isAllDay Boolean True when no time was parsed
confidence ParseConfidence HIGH (date+time), MEDIUM (date or time), LOW (title only)

Supported Patterns

Dates

Pattern Examples
Relative today, tomorrow, yesterday, day after tomorrow
Weekday Monday, next Friday, last Tuesday
Month + day January 15, Jan 15, 15th of March
Structured 1/15, 2026-01-15, 15.01.2026, 1/15/26
Offset in 3 days, 2 weeks ago, in 6 months

Times

Pattern Examples
With meridiem 3pm, 3:30pm, 3:30 PM, 3 pm
24-hour 15:00, 9:30
Keywords noon, midnight
Ranges 9-10am, 11am-1pm, 2pm to 4pm
Duration for 2 hours, for 30 minutes

Recurrence

Pattern Examples
Frequency daily, weekly, monthly, yearly, biweekly
Interval every 2 weeks, every 3 months
Weekday every Monday, every Friday

Other

Pattern Examples
Location ... at Conference Room A
Number words one, fifteen, twenty-five

Requirements

  • JVM 11+
  • Kotlin 1.9+ (or Java 11+)

License

Apache License 2.0. See LICENSE.

About

Natural language date/time parser for Kotlin/JVM. Zero dependencies.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages