Seamless conversions between Joda Time types, Java standard library types, and Scala types with both safe and direct conversion methods. This enables smooth interoperability across different temporal APIs and type systems.
Enhanced string parsing with both direct conversion and safe option-based parsing.
/**
* Rich String operations for parsing temporal types
*/
implicit class RichString(s: String) {
// Direct parsing (throws exception on failure)
def toDateTime: DateTime
def toLocalDate: LocalDate
def toInterval: Interval
// Safe parsing (returns Option)
def toDateTimeOption: Option[DateTime]
def toLocalDateOption: Option[LocalDate]
def toIntervalOption: Option[Interval]
}Usage Examples:
import com.github.nscala_time.time.Imports._
// Direct string parsing
val dateTime = "2024-12-25T14:30:00".toDateTime
val localDate = "2024-12-25".toLocalDate
val interval = "2024-01-01/2024-12-31".toInterval
// Safe string parsing
val safeDateTime = "2024-12-25T14:30:00".toDateTimeOption // Some(DateTime)
val invalidDate = "invalid-date".toDateTimeOption // None
val safeInterval = "2024-01-01/2024-12-31".toIntervalOption // Some(Interval)
// Pattern matching with safe parsing
"2024-06-15".toLocalDateOption match {
case Some(date) => println(s"Parsed date: $date")
case None => println("Invalid date format")
}
// Batch parsing with error handling
val dateStrings = List("2024-01-01", "2024-02-01", "invalid", "2024-03-01")
val validDates = dateStrings.flatMap(_.toLocalDateOption)Conversions between Java's legacy Date/Calendar classes and Joda Time types.
/**
* Rich java.util.Date operations for Joda Time conversion
*/
implicit class RichDate(underlying: java.util.Date) {
def toLocalDateTime: LocalDateTime
def toLocalDate: LocalDate
def toLocalTime: LocalTime
}Usage Examples:
import com.github.nscala_time.time.Imports._
import java.util.Date
// Convert Java Date to Joda Time types
val javaDate = new Date()
val localDate = javaDate.toLocalDate
val localTime = javaDate.toLocalTime
val localDateTime = javaDate.toLocalDateTime
// Interoperability in legacy code
def processLegacyDate(date: Date): String = {
val localDate = date.toLocalDate
(localDate + 1.day).toString("yyyy-MM-dd")
}Bidirectional conversions between Scala's concurrent.duration.Duration and Joda Time Duration.
/**
* Rich Scala Duration for conversion to Joda Time
*/
implicit class RichSDuration(underlying: scala.concurrent.duration.Duration) {
def toJodaDuration: Duration
}
/**
* Rich Joda Duration for conversion to Scala Duration
*/
implicit class RichDuration(underlying: Duration) {
def toScalaDuration: scala.concurrent.duration.Duration
// Additional conversion utilities
def days: Long
def hours: Long
def minutes: Long
def seconds: Long
def millis: Long
}Usage Examples:
import com.github.nscala_time.time.Imports._
import scala.concurrent.duration._
// Convert Scala Duration to Joda Duration
val scalaDuration = 2.hours + 30.minutes
val jodaDuration = scalaDuration.toJodaDuration
// Convert Joda Duration to Scala Duration
val jodaDur = Duration.standardHours(3)
val scalaDur = jodaDur.toScalaDuration
// Use in concurrent contexts
import scala.concurrent.{Future, Await}
import scala.concurrent.ExecutionContext.Implicits.global
val timeout = (1.hour).toJodaDuration.toScalaDuration
val future = Future { Thread.sleep(1000); "done" }
val result = Await.result(future, timeout)
// Interoperability patterns
def scheduleTask(delay: Duration): Unit = {
val scalaDelay = delay.toScalaDuration
// Use with Akka, Scala futures, etc.
}
def createJodaInterval(scalaDuration: scala.concurrent.duration.Duration): Interval = {
val start = DateTime.now
val end = start + scalaDuration.toJodaDuration
new Interval(start, end)
}Conversions between numeric types and temporal types.
/**
* Rich Long operations for temporal conversions
*/
implicit class RichLong(n: Long) {
def toDateTime: DateTime // Interpret as milliseconds since epoch
def toDuration: Duration // Interpret as milliseconds
// Arithmetic operations with durations
def +(duration: Duration): Duration
def -(duration: Duration): Duration
def *(duration: Duration): Duration
}
/**
* Rich Int operations for temporal conversions and arithmetic
*/
implicit class RichInt(n: Int) {
def *(period: Period): Period // Multiply period by scalar
def toDuration: Duration // Interpret as milliseconds
}Usage Examples:
import com.github.nscala_time.time.Imports._
// Convert milliseconds to DateTime
val timestamp = 1640995200000L // 2022-01-01 00:00:00 UTC
val dateTime = timestamp.toDateTime
val utcDateTime = timestamp.toDateTime(DateTimeZone.UTC)
// Convert to Duration
val durationFromMillis = 3600000L.toDuration // 1 hour
val durationFromInt = 5000.toDuration // 5 seconds
// Arithmetic with numeric values
val longDuration = 1800000L // 30 minutes in milliseconds
val enhanced = longDuration + Duration.standardMinutes(15) // 45 minutes
// Period multiplication
val dailyPeriod = 1.day
val weeklyPeriod = 7 * dailyPeriod
// Timestamp manipulation
def addMilliseconds(dateTime: DateTime, millis: Long): DateTime = {
dateTime + millis.toDuration
}Operations that enable arithmetic between different temporal types with automatic conversions.
/**
* Cross-type arithmetic operations enabled by implicit conversions
*/
// DateTime with various types
DateTime + Long // DateTime + milliseconds -> DateTime
DateTime + Duration // DateTime + Duration -> DateTime
DateTime + Period // DateTime + Period -> DateTime
DateTime + DurationBuilder // DateTime + DurationBuilder -> DateTime
// Duration with various types
Duration + Long // Duration + milliseconds -> Duration
Duration + Duration // Duration + Duration -> Duration
Long + Duration // milliseconds + Duration -> Duration
// Period with various types
Period + Period // Period + Period -> Period
Int * Period // scalar * Period -> PeriodUsage Examples:
import com.github.nscala_time.time.Imports._
val baseTime = DateTime.now
// Mixed arithmetic operations
val result1 = baseTime + 3600000L + Duration.standardMinutes(30) + 2.hours
val result2 = baseTime + Period.days(1) + 12.hours + 1800000L
// Chained conversions and operations
val complexCalculation = DateTime.now
.plus(Duration.standardHours(2))
.plus(Period.days(1))
.plus(30.minutes.toDuration)
.plus(1800000L.toDuration)
// Duration arithmetic across types
val totalDuration = Duration.standardHours(1) +
1800000L +
30.minutes.toDuration +
scala.concurrent.duration.Duration(15, "minutes").toJodaDurationConverting temporal objects to various string representations and formats.
/**
* Enhanced formatting capabilities through Joda Time integration
*/
implicit class RichDateTime(underlying: DateTime) {
// Inherited formatting methods from Joda Time, enhanced with Scala syntax
def toString(pattern: String): String
def toString(formatter: DateTimeFormatter): String
}
implicit class RichLocalDate(underlying: LocalDate) {
def toString(pattern: String): String
def toString(formatter: DateTimeFormatter): String
}
implicit class RichLocalTime(underlying: LocalTime) {
def toString(pattern: String): String
def toString(formatter: DateTimeFormatter): String
}
implicit class RichLocalDateTime(underlying: LocalDateTime) {
def toString(pattern: String): String
def toString(formatter: DateTimeFormatter): String
}Usage Examples:
import com.github.nscala_time.time.Imports._
val dateTime = DateTime.now
val localDate = LocalDate.now
val localTime = LocalTime.now
// Pattern-based formatting
val isoFormat = dateTime.toString("yyyy-MM-dd'T'HH:mm:ss")
val readable = dateTime.toString("MMMM dd, yyyy 'at' HH:mm")
val dateOnly = localDate.toString("yyyy-MM-dd")
val timeOnly = localTime.toString("HH:mm:ss")
// Predefined formatters
val isoDateTime = dateTime.toString(ISODateTimeFormat.dateTime())
val basicDate = localDate.toString(DateTimeFormat.forPattern("yyyyMMdd"))
// Locale-specific formatting
val formatter = DateTimeFormat.forStyle("MS").withLocale(java.util.Locale.US)
val usFormat = dateTime.toString(formatter)
// Custom formatting for different contexts
def formatForApi(dt: DateTime): String = dt.toString("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
def formatForDisplay(dt: DateTime): String = dt.toString("MMM dd, yyyy 'at' h:mm a")
def formatForFilename(dt: DateTime): String = dt.toString("yyyyMMdd_HHmmss")import com.github.nscala_time.time.Imports._
import java.util.{Date, Calendar}
import java.sql.Timestamp
// Convert legacy types to Joda Time for processing
def processLegacyTimestamp(timestamp: Timestamp): DateTime = {
new DateTime(timestamp.getTime)
}
def convertCalendarEvent(cal: Calendar): (LocalDate, LocalTime) = {
val jodaDateTime = cal.toDateTime
(jodaDateTime.toLocalDate, jodaDateTime.toLocalTime)
}
// Convert back to legacy types when needed
def toJavaDate(dt: DateTime): Date = dt.toDate
def toSqlTimestamp(dt: DateTime): Timestamp = new Timestamp(dt.getMillis)import com.github.nscala_time.time.Imports._
// Common patterns for JSON serialization
case class Event(
name: String,
startTime: DateTime,
duration: Duration
)
object Event {
// Serialization helpers
def serializeDateTime(dt: DateTime): String = dt.toString()
def deserializeDateTime(s: String): Option[DateTime] = s.toDateTimeOption
def serializeDuration(dur: Duration): Long = dur.getMillis
def deserializeDuration(millis: Long): Duration = millis.toDuration
}import com.github.nscala_time.time.Imports._
import java.sql.{Timestamp, Date => SqlDate, Time => SqlTime}
// Database conversion utilities
object DatabaseConverters {
def toTimestamp(dt: DateTime): Timestamp = new Timestamp(dt.getMillis)
def fromTimestamp(ts: Timestamp): DateTime = new DateTime(ts.getTime)
def toSqlDate(ld: LocalDate): SqlDate = new SqlDate(ld.toDateTimeAtStartOfDay.getMillis)
def fromSqlDate(date: SqlDate): LocalDate = new DateTime(date.getTime).toLocalDate
def toSqlTime(lt: LocalTime): SqlTime = new SqlTime(lt.getMillisOfDay)
def fromSqlTime(time: SqlTime): LocalTime = LocalTime.fromMillisOfDay(time.getTime)
}