Swift 的工具包,用于解析、验证、操作、比较和显示日期、时间和时区。
这是什么?
SwiftDate 是操作和显示所有 Apple 平台以及 Linux 平台(如 Vapor 或 Kitura)上日期和时间区间的 终极工具链。
在 CocoaPods 上下载量超过 300 万。
从简单的日期操作到复杂的企业逻辑,SwiftDate 可能是您下一个项目的正确选择。
- 简单的日期解析(自定义格式、ISO8601、RSS 等)
- 简单的日期格式化,即使使用口语化格式器和 140 多种支持的语言
- 使用时间单位进行简单数学运算(如
2.hours + 5.minutes
...) - 直观的组件提取(如
day, hour, nearestHour, weekdayNameShort
等。) - 派生日期生成(如
nextWeek, nextMonth, nextWeekday, tomorrow
...) - 超过 20多个精细的日期比较函数(如
isToday, isTomorrow, isSameWeek, isNextYear
...) - Swift 4 的 Codable 支持
- 随机日期生成
- 精细的日期枚举函数
- 时间段支持
- 转换时间间隔为其他单位(如
2.hours.toUnits(.minutes)
)
当然...
- 经过测试!。从 5.x 版本开始,该项目有 90% 的代码覆盖率(想帮助我们?编写一些单元测试并提交 PR)
- 详尽文档!,提供了完整的指南,以及 Jazzy!
- 我们热爱 Playgrounds! 查看我们的交互式 Playgrounds!
从 SwiftDate 开始
整个库都通过 XCode 方法检查器和下方的完整 markdown 文档进行了全面文档化。
- → 完整文档
- → 需求、安装、许可与更多
- → 从 SwiftDate 4 升级
探索 SwiftDate
从简单的日期操作到复杂的企业逻辑,SwiftDate 可能是您下一个项目的正确选择。
让我向您展示这个库的主要功能
1. 日期解析
SwiftDate 可以自动识别所有主要的日期时间格式(ISO8601、RSS、Alt RSS、.NET、SQL、HTTP...),您也可以提供自己的格式。创建新日期从未如此容易!
// All default datetime formats (15+) are recognized automatically
let _ = "2010-05-20 15:30:00".toDate()
// You can also provide your own format!
let _ = "2010-05-20 15:30".toDate("yyyy-MM-dd HH:mm")
// All ISO8601 variants are supported too with timezone parsing!
let _ = "2017-09-17T11:59:29+02:00".toISODate()
// RSS, Extended, HTTP, SQL, .NET and all the major variants are supported!
let _ = "19 Nov 2015 22:20:40 +0100".toRSS(alt: true)
2. 日期操作
日期可以通过使用自然语言添加或删除时间组件进行操作;时间单位提取也很容易,并支持时区、日历和地区!
可以使用标准数学运算符以及日期、时间间隔、日期组件和相关的时间单位进行操作!
// Math operations support time units
let _ = ("2010-05-20 15:30:00".toDate() + 3.months - 2.days)
let _ = Date() + 3.hours
let _ = date1 + [.year:1, .month:2, .hour:5]
let _ = date1 + date2
// extract single time unit components from date manipulation
let over1Year = (date3 - date2).year > 1
3. 日期比较
SwiftDate 包含一个广泛的比较函数集;您可以通过粒度比较两个日期,检查一个日期是否是特定的日期,范围和实际上您需要的任何其他比较。
比较也可以通过标准数学运算符,如(>、>=、<、<=)来进行。
// Standard math comparison is allowed
let _ = dateA >= dateB || dateC < dateB
// Complex comparisons includes granularity support
let _ = dateA.compare(toDate: dateB, granularity: .hour) == .orderedSame
let _ = dateA.isAfterDate(dateB, orEqual: true, granularity: .month) // > until month granularity
let _ = dateC.isInRange(date: dateA, and: dateB, orEqual: true, granularity: .day) // > until day granularity
let _ = dateA.earlierDate(dateB) // earlier date
let _ = dateA.laterDate(dateB) // later date
// Check if date is close to another with a given precision
let _ = dateA.compareCloseTo(dateB, precision: 1.hours.timeInterval
// Compare for relevant events:
// .isToday, .isYesterday, .isTomorrow, .isWeekend, isNextWeek
// .isSameDay, .isMorning, .isWeekday ...
let _ = date.compare(.isToday)
let _ = date.compare(.isNight)
let _ = date.compare(.isNextWeek)
let _ = date.compare(.isThisMonth)
let _ = date.compare(.startOfWeek)
let _ = date.compare(.isNextYear)
// ...and MORE THAN 30 OTHER COMPARISONS BUILT IN
// Operation in arrays (oldestIn, newestIn, sortedByNewest, sortedByOldest...)
let _ = DateInRegion.oldestIn(list: datesArray)
let _ = DateInRegion.sortedByNewest(list: datesArray)
4. 使用区域(时区、日历和区域设置)创建日期
您可以从字符串、时间间隔或使用日期组件创建新的日期。SwiftDate提供了一个广泛的函数,以创建和派生您的日期,甚至可以使用随机生成!
// All dates includes timezone, calendar and locales!
// Create from string
let rome = Region(calendar: Calendars.gregorian, zone: Zones.europeRome, locale: Locales.italian)
let date1 = DateInRegion("2010-01-01 00:00:00", region: rome)!
// Create date from intervals
let _ = DateInRegion(seconds: 39940, region: rome)
let _ = DateInRegion(milliseconds: 5000, region: rome)
// Date from components
let _ = DateInRegion(components: {
$0.year = 2001
$0.month = 9
$0.day = 11
$0.hour = 12
$0.minute = 0
}, region: rome)
let _ = DateInRegion(year: 2001, month: 1, day: 5, hour: 23, minute: 30, second: 0, region: rome)
// Random date generation with/without bounds
let _ = DateInRegion.randomDate(region: rome)
let _ = DateInRegion.randomDate(withinDaysBeforeToday: 5)
let _ = DateInRegion.randomDates(count: 50, between: lowerLimitDate, and: upperLimitDate, region: rome)
5. 派生日期
日期也可以从其他日期生成;SwiftDate包括了一整套用于生成的函数。使用dateAt()
函数,可以轻松地创建20多种派生日期。
let _ = DateInRegion().dateAt(.endOfDay) // today at the end of the day
// Over 20 different relevant dates including .startOfDay,
// .endOfDay, .startOfWeek, .tomorrow, .nextWeekday, .nextMonth, .prevYear, .nearestMinute and many others!
let _ = dateA.nextWeekday(.friday) // the next friday after dateA
let _ = (date.dateAt(.startOfMonth) - 3.days)
let _ = dateA.compare(.endOfWeek)
// Enumerate dates in range by providing your own custom
// increment expressed in date components
let from = DateInRegion("2015-01-01 10:00:00", region: rome)!
let to = DateInRegion("2015-01-02 03:00:00", region: rome)!
let increment2 = DateComponents.create {
$0.hour = 1
$0.minute = 30
$0.second = 10
}
// generate dates in range by incrementing +1h,30m,10s each new date
let dates = DateInRegion.enumerateDates(from: fromDate2, to: toDate2, increment: increment2)
// Get all mondays in Jan 2019
let mondaysInJan2019 = Date.datesForWeekday(.monday, inMonth: 1, ofYear: 2019)
// Altering time components
let _ = dateA.dateBySet(hour: 10, min: 0, secs: 0)
// Truncating a date
let _ = dateA.dateTruncated(at: [.year,.month,.day]) // reset all time components keeping only date
// Rounding a date
let _ = dateA.dateRoundedAt(.toMins(10))
let _ = dateA.dateRoundedAt(.toFloor30Mins)
// Adding components
let _ = dateA.dateByAdding(5,.year)
// Date at the start/end of any time component
let _ = dateA.dateAtEndOf(.year) // 31 of Dec at 23:59:59
let _ = dateA.dateAtStartOf(.day) // at 00:00:00 of the same day
let _ = dateA.dateAtStartOf(.month) // at 00:00:00 of the first day of the month
6. 组件提取
您可以从日期中直接提取组件,并且包含日期所在地区表示的正确值(正确的时区和设置的区域设置!)。
// Create a date in a region, London but with the lcoale set to IT
let london = Region(calendar: .gregorian, zone: .europeLondon, locale: .italian)
let date = DateInRegion("2018-02-05 23:14:45", format: dateFormat, region: london)!
// You can extract any of the all available time units.
// VALUES ARE EXPRESSED IN THE REGION OF THE DATE (THE RIGHT TIMEZONE).
// (you can still get the UTC/absolute value by getting the inner's absoluteDate).
let _ = date.year // 2018
let _ = date.month // 2
let _ = date.monthNameDefault // 'Febbraio' as the locale is the to IT!
let _ = date.firstDayOfWeek // 5
let _ = date.weekdayNameShort // 'Lun' as locale is the to IT
// ... all components are supported: .year, .month, .day, .hour, .minute, .second,
// .monthName, .weekday, .nearestHour, .firstDayOfWeek. .quarter and so on...
7. 在时区/区域设置和日历间切换
您可以轻松地将任何日期转换为另一个区域(也称为另一个日历、区域设置或时区)!新日期包含在目标区域中表达的所有值。
// Conversion between timezones is easy using convertTo(region:) function
let rNY = Region(calendar: Calendars.gregorian, zone: Zones.americaNewYork, locale: Locales.english)
let rRome = Region(calendar: Calendars.gregorian, zone: Zones.europeRome, locale: Locales.italian)
let dateInNY = "2017-01-01 00:00:00".toDate(region: rNY)
let dateInRome = dateInNY?.convertTo(region: rRome)!
print(dateInRome.toString()) // "dom gen 01 06:00:00 +0100 2017\n"
// You can also convert single region's attributes
let dateInIndia = dateInNY?.convertTo(timezone: Zones.indianChristmas, locale: Locales.nepaliIndia)
print("\(dateInIndia!.toString())") // "आइत जनवरी ०१ १२:००:०० +0700 २०१७\n"
8. 日期格式化
日期格式化很容易,您可以指定自己的格式、区域设置或使用提供的任一格式。
// Date Formatting
let london = Region(calendar: .gregorian, zone: .europeLondon, locale: .english)
let date = ... // 2017-07-22T18:27:02+02:00 in london region
let _ = date.toDotNET() // /Date(1500740822000+0200)/
let _ = date.toISODate() // 2017-07-22T18:27:02+02:00
let _ = date.toFormat("dd MMM yyyy 'at' HH:mm") // "22 July 2017 at 18:27"
// You can also easily change locale when formatting a region
let _ = date.toFormat("dd MMM", locale: .italian) // "22 Luglio"
// Time Interval Formatting as Countdown
let interval: TimeInterval = (2.hours.timeInterval) + (34.minutes.timeInterval) + (5.seconds.timeInterval)
let _ = interval.toClock() // "2:34:05"
// Time Interval Formatting by Components
let _ = interval.toString {
$0.maximumUnitCount = 4
$0.allowedUnits = [.day, .hour, .minute]
$0.collapsesLargestUnit = true
$0.unitsStyle = .abbreviated
} // "2h 34m"
9. 相对日期格式化(完全可自定义)
SwiftDate引入了全新的相对日期格式化功能,支持120多种语言,两种格式(.default, .twitter)和9种风格(.long, .longTime, .longConvenient, .short, .shortTime, .shortConvenient, .narrow, .tiny, .quantify),所有这些都可以按需自定义。扩展的格式允许你提供自己的翻译和规则来覆盖默认行为。
// Twitter Style
let _ = (Date() - 3.minutes).toRelative(style: RelativeFormatter.twitterStyle(), locale: Locales.english) // "3m"
let _ = (Date() - 6.minutes).toRelative(style: RelativeFormatter.twitterStyle(), locale: Locales.italian) // "6 min fa"
// Default Style
let _ = (now2 - 5.hours).toRelative(style: RelativeFormatter.defaultStyle(), locale: Locales.english) // "5 hours ago"
let y = (now2 - 40.minutes).toRelative(style: RelativeFormatter.defaultStyle(), locale: Locales.italian) // "45 minuti fa"
10. Codable支持
DateInRegion
和Region
都完全支持Swift的新Codable
协议。这意味着你可以安全地对它们进行编码和解码。
// Encoding/Decoding a Region
let region = Region(calendar: Calendars.gregorian, zone: Zones.europeOslo, locale: Locales.english)
let encodedJSON = try JSONEncoder().encode(region)
let decodedRegion = try JSONDecoder().decode(Region.self, from: encodedJSON)
// Encoding/Decoding a DateInRegion
let date = DateInRegion("2015-09-24T13:20:55", region: region)
let encodedDate = try JSONEncoder().encode(date)
let decodedDate = try JSONDecoder().decode(DateInRegion.self, from: encodedDate)
11. 时间段
SwiftDate集成了Matthew York的 DateTools模块,以支持时间段。
请参阅文档中的时间段部分。