Apache Commons Lang provides essential Java utility classes for string manipulation, object operations, array handling, date/time processing, reflection utilities, and more.
—
Apache Commons Lang provides comprehensive date and time utilities through DateUtils, StopWatch, and various formatting classes. These utilities offer safe date manipulation, performance timing, and flexible formatting options that complement Java's standard date/time API.
Provides 52 static methods for date arithmetic, comparison, and manipulation:
import org.apache.commons.lang3.time.DateUtils;// Time unit constants in milliseconds
public static final long MILLIS_PER_SECOND = 1000L
public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND
public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE
public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR
// Calendar field constants
public static final int SEMI_MONTH = 1001
// Range iteration constants
public static final int RANGE_WEEK_SUNDAY = 1
public static final int RANGE_WEEK_MONDAY = 2
public static final int RANGE_WEEK_RELATIVE = 3
public static final int RANGE_WEEK_CENTER = 4
public static final int RANGE_MONTH_SUNDAY = 5
public static final int RANGE_MONTH_MONDAY = 6// Add time units to dates (returns new Date)
public static Date addYears(Date date, int amount)
public static Date addMonths(Date date, int amount)
public static Date addWeeks(Date date, int amount)
public static Date addDays(Date date, int amount)
public static Date addHours(Date date, int amount)
public static Date addMinutes(Date date, int amount)
public static Date addSeconds(Date date, int amount)
public static Date addMilliseconds(Date date, int amount)Usage Examples:
Date now = new Date();
// Adding time units
Date nextWeek = DateUtils.addWeeks(now, 1); // 7 days from now
Date nextMonth = DateUtils.addMonths(now, 1); // 1 month from now
Date nextYear = DateUtils.addYears(now, 1); // 1 year from now
Date tomorrow = DateUtils.addDays(now, 1); // Tomorrow
Date inTwoHours = DateUtils.addHours(now, 2); // 2 hours from now
// Subtracting time (use negative amounts)
Date lastWeek = DateUtils.addDays(now, -7); // 7 days ago
Date lastMonth = DateUtils.addMonths(now, -1); // 1 month ago
Date tenMinutesAgo = DateUtils.addMinutes(now, -10); // 10 minutes ago
// Combining operations
Date futureDate = DateUtils.addDays(
DateUtils.addHours(now, 2), 5); // 5 days and 2 hours from now// Truncate dates to specific calendar fields
public static Date truncate(Date date, int field)
public static Calendar truncate(Calendar date, int field)
// Round dates up to next calendar field boundary
public static Date ceiling(Date date, int field)
public static Calendar ceiling(Calendar date, int field)
// Round dates to nearest calendar field boundary
public static Date round(Date date, int field)
public static Calendar round(Calendar date, int field)Usage Examples:
Date now = new Date(); // 2024-03-15 14:30:45.123
// Truncation (set lower fields to minimum)
Date dayStart = DateUtils.truncate(now, Calendar.DAY_OF_MONTH); // 2024-03-15 00:00:00.000
Date hourStart = DateUtils.truncate(now, Calendar.HOUR_OF_DAY); // 2024-03-15 14:00:00.000
Date monthStart = DateUtils.truncate(now, Calendar.MONTH); // 2024-03-01 00:00:00.000
Date yearStart = DateUtils.truncate(now, Calendar.YEAR); // 2024-01-01 00:00:00.000
// Ceiling (round up to next boundary)
Date nextDay = DateUtils.ceiling(now, Calendar.DAY_OF_MONTH); // 2024-03-16 00:00:00.000
Date nextHour = DateUtils.ceiling(now, Calendar.HOUR_OF_DAY); // 2024-03-15 15:00:00.000
Date nextMonth = DateUtils.ceiling(now, Calendar.MONTH); // 2024-04-01 00:00:00.000
// Rounding (to nearest boundary)
Date rounded = DateUtils.round(now, Calendar.HOUR_OF_DAY); // 2024-03-15 15:00:00.000 (rounds up at 30+ minutes)// Date comparison methods
public static boolean isSameDay(Date date1, Date date2)
public static boolean isSameDay(Calendar cal1, Calendar cal2)
public static boolean isSameInstant(Date date1, Date date2)
public static boolean isSameInstant(Calendar cal1, Calendar cal2)
public static boolean isSameLocalTime(Calendar cal1, Calendar cal2)Usage Examples:
Date date1 = new Date();
Date date2 = DateUtils.addHours(date1, 5); // Same day, different time
Date date3 = DateUtils.addDays(date1, 1); // Different day
// Same day comparison (ignores time)
boolean sameDay = DateUtils.isSameDay(date1, date2); // true
boolean differentDay = DateUtils.isSameDay(date1, date3); // false
// Same instant comparison (exact timestamp)
boolean sameInstant = DateUtils.isSameInstant(date1, date1); // true
boolean differentInstant = DateUtils.isSameInstant(date1, date2); // false
// Calendar comparison
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
boolean sameLocalTime = DateUtils.isSameLocalTime(cal1, cal2); // false// Parse dates with multiple format attempts
public static Date parseDate(String str, String... parsePatterns) throws ParseException
public static Date parseDate(String str, Locale locale, String... parsePatterns) throws ParseException
public static Date parseDateStrictly(String str, String... parsePatterns) throws ParseException
public static Date parseDateStrictly(String str, Locale locale, String... parsePatterns) throws ParseExceptionUsage Examples:
// Multiple format parsing
String[] patterns = {
"yyyy-MM-dd",
"dd/MM/yyyy",
"MM-dd-yyyy",
"yyyy-MM-dd HH:mm:ss"
};
try {
// Try multiple formats until one succeeds
Date date1 = DateUtils.parseDate("2024-03-15", patterns); // Uses first pattern
Date date2 = DateUtils.parseDate("15/03/2024", patterns); // Uses second pattern
Date date3 = DateUtils.parseDate("03-15-2024", patterns); // Uses third pattern
Date date4 = DateUtils.parseDate("2024-03-15 14:30:00", patterns); // Uses fourth pattern
// Strict parsing (no lenient parsing)
Date strict = DateUtils.parseDateStrictly("2024-02-30", patterns); // Throws ParseException
} catch (ParseException e) {
// Handle parsing failure
System.err.println("Unable to parse date: " + e.getMessage());
}
// Locale-specific parsing
try {
Date localeDate = DateUtils.parseDate("15 mars 2024", Locale.FRENCH, "dd MMMM yyyy");
} catch (ParseException e) {
// Handle error
}// Iterate over date ranges
public static Iterator<Calendar> iterator(Date focus, int rangeStyle)
public static Iterator<Calendar> iterator(Calendar focus, int rangeStyle)Usage Examples:
Date today = new Date();
// Iterate over week (Sunday to Saturday)
Iterator<Calendar> weekIterator = DateUtils.iterator(today, DateUtils.RANGE_WEEK_SUNDAY);
List<Date> weekDates = new ArrayList<>();
while (weekIterator.hasNext()) {
weekDates.add(weekIterator.next().getTime());
}
// Iterate over month view (includes partial weeks)
Iterator<Calendar> monthIterator = DateUtils.iterator(today, DateUtils.RANGE_MONTH_SUNDAY);
List<Date> monthViewDates = new ArrayList<>();
while (monthIterator.hasNext()) {
monthViewDates.add(monthIterator.next().getTime());
}
// Custom iteration
public List<Date> getDateRange(Date start, Date end) {
List<Date> dates = new ArrayList<>();
Date current = DateUtils.truncate(start, Calendar.DAY_OF_MONTH);
Date endDate = DateUtils.truncate(end, Calendar.DAY_OF_MONTH);
while (!current.after(endDate)) {
dates.add(new Date(current.getTime()));
current = DateUtils.addDays(current, 1);
}
return dates;
}Provides high-precision timing for performance monitoring and benchmarking:
import org.apache.commons.lang3.time.StopWatch;// Stopwatch creation
public static StopWatch create()
public static StopWatch createStarted()
// Timing control
public StopWatch start()
public StopWatch stop()
public StopWatch reset()
public StopWatch suspend()
public StopWatch resume()
// Time retrieval
public long getTime()
public long getTime(TimeUnit timeUnit)
public long getNanoTime()
public long getSplitTime()
public long getSplitNanoTime()Usage Examples:
// Basic timing
StopWatch stopwatch = StopWatch.createStarted();
performExpensiveOperation();
stopwatch.stop();
long milliseconds = stopwatch.getTime(); // Time in milliseconds
long nanoseconds = stopwatch.getNanoTime(); // Time in nanoseconds
long seconds = stopwatch.getTime(TimeUnit.SECONDS); // Time in seconds
System.out.println("Operation took: " + milliseconds + "ms");
// Reusable stopwatch
StopWatch reusableTimer = StopWatch.create();
for (int i = 0; i < 10; i++) {
reusableTimer.reset();
reusableTimer.start();
performOperation(i);
reusableTimer.stop();
System.out.printf("Iteration %d: %dms%n", i, reusableTimer.getTime());
}// Split timing (lap times)
StopWatch lapTimer = StopWatch.createStarted();
performTask1();
lapTimer.split();
long task1Time = lapTimer.getSplitTime();
System.out.println("Task 1: " + task1Time + "ms");
performTask2();
lapTimer.split();
long task2Time = lapTimer.getSplitTime() - task1Time;
System.out.println("Task 2: " + task2Time + "ms");
lapTimer.stop();
long totalTime = lapTimer.getTime();
System.out.println("Total: " + totalTime + "ms");
// Suspend and resume
StopWatch pausableTimer = StopWatch.createStarted();
performPartialTask();
pausableTimer.suspend(); // Pause timing
handleInterruption(); // This time is not counted
pausableTimer.resume(); // Resume timing
completeTask();
pausableTimer.stop();
long actualWorkTime = pausableTimer.getTime(); // Only counts non-suspended timeProvides thread-safe date formatting utilities:
import org.apache.commons.lang3.time.DateFormatUtils;// ISO format constants
public static final FastDateFormat ISO_DATETIME_FORMAT // yyyy-MM-dd'T'HH:mm:ss
public static final FastDateFormat ISO_DATETIME_TIME_ZONE_FORMAT // yyyy-MM-dd'T'HH:mm:ssZZ
public static final FastDateFormat ISO_DATE_FORMAT // yyyy-MM-dd
public static final FastDateFormat ISO_TIME_NO_T_FORMAT // HH:mm:ss
public static final FastDateFormat ISO_TIME_NO_T_TIME_ZONE_FORMAT // HH:mm:ssZZ// Format dates with patterns
public static String format(Date date, String pattern)
public static String format(Date date, String pattern, Locale locale)
public static String format(Date date, String pattern, TimeZone timeZone)
public static String format(Date date, String pattern, TimeZone timeZone, Locale locale)
// Format timestamps
public static String format(long millis, String pattern)
public static String format(long millis, String pattern, Locale locale)
public static String format(long millis, String pattern, TimeZone timeZone)
// Format Calendar objects
public static String format(Calendar calendar, String pattern)
public static String format(Calendar calendar, String pattern, Locale locale)
public static String format(Calendar calendar, String pattern, TimeZone timeZone)Usage Examples:
Date now = new Date();
// Basic formatting
String date1 = DateFormatUtils.format(now, "yyyy-MM-dd"); // "2024-03-15"
String date2 = DateFormatUtils.format(now, "dd/MM/yyyy HH:mm:ss"); // "15/03/2024 14:30:45"
String date3 = DateFormatUtils.format(now, "EEEE, MMMM d, yyyy"); // "Friday, March 15, 2024"
// ISO formats
String iso1 = DateFormatUtils.ISO_DATE_FORMAT.format(now); // "2024-03-15"
String iso2 = DateFormatUtils.ISO_DATETIME_FORMAT.format(now); // "2024-03-15T14:30:45"
// Timezone and locale formatting
TimeZone utc = TimeZone.getTimeZone("UTC");
String utcDate = DateFormatUtils.format(now, "yyyy-MM-dd HH:mm:ss", utc); // UTC time
Locale french = Locale.FRENCH;
String frenchDate = DateFormatUtils.format(now, "EEEE d MMMM yyyy", french); // "vendredi 15 mars 2024"
// Timestamp formatting
long timestamp = System.currentTimeMillis();
String formatted = DateFormatUtils.format(timestamp, "yyyy-MM-dd HH:mm:ss.SSS");Provides utilities for formatting time durations:
import org.apache.commons.lang3.time.DurationFormatUtils;// Format duration in milliseconds
public static String formatDuration(long durationMillis, String format)
public static String formatDuration(long durationMillis, String format, boolean padWithZeros)
// Predefined formats
public static String formatDurationHMS(long durationMillis) // H:mm:ss
public static String formatDurationISO(long durationMillis) // ISO 8601 duration
// Format periods between two timestamps
public static String formatPeriod(long startMillis, long endMillis, String format)
public static String formatPeriodISO(long startMillis, long endMillis)
// Human-readable duration
public static String formatDurationWords(long durationMillis, boolean suppressLeadingZeroElements, boolean suppressTrailingZeroElements)Usage Examples:
long duration = 3_661_000L; // 1 hour, 1 minute, 1 second in milliseconds
// Basic formatting
String formatted1 = DurationFormatUtils.formatDuration(duration, "HH:mm:ss"); // "01:01:01"
String formatted2 = DurationFormatUtils.formatDuration(duration, "H:mm:ss"); // "1:01:01"
String formatted3 = DurationFormatUtils.formatDuration(duration, "H 'hours', m 'minutes', s 'seconds'"); // "1 hours, 1 minutes, 1 seconds"
// Predefined formats
String hms = DurationFormatUtils.formatDurationHMS(duration); // "1:01:01"
String iso = DurationFormatUtils.formatDurationISO(duration); // "PT1H1M1S"
// Human-readable format
String words = DurationFormatUtils.formatDurationWords(duration, true, true); // "1 hour 1 minute 1 second"
// Period formatting
long start = System.currentTimeMillis();
Thread.sleep(5000); // Simulate 5-second operation
long end = System.currentTimeMillis();
String period = DurationFormatUtils.formatPeriod(start, end, "ss.SSS 'seconds'"); // "5.000 seconds"
String isoPeriod = DurationFormatUtils.formatPeriodISO(start, end); // "PT5S"public class CustomDateUtils {
// Business day calculations
public static Date addBusinessDays(Date date, int businessDays) {
Date result = new Date(date.getTime());
int added = 0;
while (added < businessDays) {
result = DateUtils.addDays(result, 1);
Calendar cal = Calendar.getInstance();
cal.setTime(result);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
if (dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY) {
added++;
}
}
return result;
}
// Age calculation
public static int calculateAge(Date birthDate, Date currentDate) {
Calendar birth = Calendar.getInstance();
Calendar current = Calendar.getInstance();
birth.setTime(birthDate);
current.setTime(currentDate);
int age = current.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
if (current.get(Calendar.DAY_OF_YEAR) < birth.get(Calendar.DAY_OF_YEAR)) {
age--;
}
return age;
}
// Quarter calculations
public static int getQuarter(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return (cal.get(Calendar.MONTH) / 3) + 1;
}
public static Date getQuarterStart(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int quarter = getQuarter(date);
int startMonth = (quarter - 1) * 3;
cal.set(Calendar.MONTH, startMonth);
return DateUtils.truncate(cal.getTime(), Calendar.MONTH);
}
// Time zone conversions
public static Date convertTimeZone(Date date, TimeZone from, TimeZone to) {
long offset = to.getOffset(date.getTime()) - from.getOffset(date.getTime());
return new Date(date.getTime() + offset);
}
}public class PerformanceMonitor {
private final Map<String, StopWatch> timers = new ConcurrentHashMap<>();
private final Map<String, List<Long>> measurements = new ConcurrentHashMap<>();
// Start timing an operation
public void startTimer(String operation) {
StopWatch timer = timers.computeIfAbsent(operation, k -> StopWatch.create());
timer.reset();
timer.start();
}
// Stop timing and record measurement
public long stopTimer(String operation) {
StopWatch timer = timers.get(operation);
if (timer != null && timer.isStarted()) {
timer.stop();
long duration = timer.getTime();
measurements.computeIfAbsent(operation, k -> new ArrayList<>()).add(duration);
return duration;
}
return -1;
}
// Get statistics for an operation
public OperationStats getStats(String operation) {
List<Long> times = measurements.get(operation);
if (times == null || times.isEmpty()) {
return null;
}
return new OperationStats(
times.size(),
Collections.min(times),
Collections.max(times),
times.stream().mapToLong(Long::longValue).average().orElse(0.0)
);
}
// Auto-timing with try-with-resources
public Timer time(String operation) {
return new Timer(operation, this);
}
public static class Timer implements AutoCloseable {
private final String operation;
private final PerformanceMonitor monitor;
private final StopWatch stopwatch;
Timer(String operation, PerformanceMonitor monitor) {
this.operation = operation;
this.monitor = monitor;
this.stopwatch = StopWatch.createStarted();
}
@Override
public void close() {
stopwatch.stop();
monitor.measurements
.computeIfAbsent(operation, k -> new ArrayList<>())
.add(stopwatch.getTime());
}
}
public static class OperationStats {
public final int count;
public final long min;
public final long max;
public final double average;
OperationStats(int count, long min, long max, double average) {
this.count = count;
this.min = min;
this.max = max;
this.average = average;
}
@Override
public String toString() {
return String.format("Count: %d, Min: %dms, Max: %dms, Avg: %.2fms",
count, min, max, average);
}
}
}
// Usage example
PerformanceMonitor monitor = new PerformanceMonitor();
// Manual timing
monitor.startTimer("database-query");
executeQuery();
long queryTime = monitor.stopTimer("database-query");
// Auto timing with try-with-resources
try (PerformanceMonitor.Timer timer = monitor.time("api-call")) {
callExternalApi();
}
// Get statistics
OperationStats stats = monitor.getStats("database-query");
System.out.println("Database query stats: " + stats);@Service
public class DateService {
private static final String[] DATE_PATTERNS = {
"yyyy-MM-dd",
"dd/MM/yyyy",
"MM-dd-yyyy HH:mm:ss",
"yyyy-MM-dd'T'HH:mm:ss",
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
};
public Date parseFlexibleDate(String dateStr) throws ParseException {
if (StringUtils.isBlank(dateStr)) {
throw new IllegalArgumentException("Date string cannot be blank");
}
return DateUtils.parseDate(dateStr.trim(), DATE_PATTERNS);
}
public boolean isBusinessDay(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
return dayOfWeek >= Calendar.MONDAY && dayOfWeek <= Calendar.FRIDAY;
}
@Cacheable("date-ranges")
public List<Date> getDateRange(Date start, Date end) {
List<Date> dates = new ArrayList<>();
Date current = DateUtils.truncate(start, Calendar.DAY_OF_MONTH);
Date endDate = DateUtils.truncate(end, Calendar.DAY_OF_MONTH);
while (!current.after(endDate)) {
dates.add(new Date(current.getTime()));
current = DateUtils.addDays(current, 1);
}
return dates;
}
}@ConfigurationProperties(prefix = "app.timing")
@Data
public class TimingConfiguration {
private Duration cacheTimeout = Duration.ofMinutes(30);
private Duration requestTimeout = Duration.ofSeconds(30);
private String dateFormat = "yyyy-MM-dd HH:mm:ss";
private String timeZone = "UTC";
public FastDateFormat getDateFormatter() {
TimeZone tz = TimeZone.getTimeZone(timeZone);
return FastDateFormat.getInstance(dateFormat, tz);
}
public String formatCurrentTime() {
return getDateFormatter().format(new Date());
}
}@Component
public class AuditLogger {
private final FastDateFormat timestampFormat =
FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSS");
public void logOperation(String operation, Runnable task) {
StopWatch stopwatch = StopWatch.createStarted();
String startTime = timestampFormat.format(new Date());
try {
task.run();
stopwatch.stop();
log.info("Operation '{}' started at {} and completed in {}ms",
operation, startTime, stopwatch.getTime());
} catch (Exception e) {
stopwatch.stop();
log.error("Operation '{}' started at {} and failed after {}ms: {}",
operation, startTime, stopwatch.getTime(), e.getMessage());
throw e;
}
}
public void logScheduledTask(String taskName, Date scheduledTime, Date actualTime) {
long delay = actualTime.getTime() - scheduledTime.getTime();
String delayFormat = DurationFormatUtils.formatDurationWords(Math.abs(delay), true, true);
if (delay > 0) {
log.warn("Task '{}' executed {} late (scheduled: {}, actual: {})",
taskName, delayFormat,
timestampFormat.format(scheduledTime),
timestampFormat.format(actualTime));
} else {
log.info("Task '{}' executed on time at {}",
taskName, timestampFormat.format(actualTime));
}
}
}The date/time utilities in Apache Commons Lang provide essential functionality for date manipulation, performance timing, and formatting that complements Java's built-in date/time capabilities while offering better null safety and more convenient APIs.
Install with Tessl CLI
npx tessl i tessl/maven-org-apache-commons--commons-lang3