Библиотека для юридически значимого подсчёта дней (календарных, рабочих) с учётом российских праздников и переносов выходных дней.
- 📅 Точные расчёты: Учёт российских праздников и переносов выходных дней
- ⚖️ Юридическая точность: Соответствие Трудовому кодексу РФ
- 🏛️ Полный календарь: Данные с 2015 по 2026 год включительно
- 🔧 Простота использования: Чистый Swift API
- 📱 Кроссплатформенность: iOS 15+ и macOS 13+
- 🎯 Расширения типов: Удобные методы для
DateиInt
В Xcode выберите File > Swift Packages > Add Package Dependency и введите:
https://github.com/SergeiKriukov/DateCalc.git
Или добавьте в ваш Package.swift:
dependencies: [
.package(url: "https://github.com/SergeiKriukov/DateCalc.git", .upToNextMajor(from: "1.0.0"))
]- Скачайте папку
Sources/DateCalc - Перетащите её в ваш Xcode проект
- Убедитесь, что включены опции
Copy items if neededиCreate groups
import DateCalc
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
// Подсчёт рабочих дней между датами
let workingDays = daysBetweenDates(
country: "RU",
region: "",
subregion: "",
calendarType: "working",
startDate: Date(),
endDate: Date().byAdding(30),
includeFirstDay: false
)
Text("Рабочих дней: \(workingDays.1.count)")
// Определение даты через N рабочих дней
let futureDate = dateAfterDays(
country: "RU",
region: "",
subregion: "",
calendarType: "working",
initialDate: Date(),
days: 10,
workingDaysOnly: true,
directionFuture: true
)
Text("Дата через 10 рабочих дней: \(futureDate.0.shortFormat)")
}
}
}Супер-функция для расчёта количества дней между двумя датами с учётом рабочих/выходных дней.
let result = daysBetweenDates(
country: "RU",
region: "",
subregion: "",
calendarType: "working",
startDate: Date(),
endDate: Date().byAdding(30),
includeFirstDay: false
)
// Возвращает: (Int, [Date], [Date], [Date], Bool, Date?)dateAfterDays(country:region:subregion:calendarType:initialDate:days:workingDaysOnly:directionFuture:)
Определяет дату через заданное количество дней от исходной даты.
let (date, description) = dateAfterDays(
country: "RU",
region: "",
subregion: "",
calendarType: "working",
initialDate: Date(),
days: 15,
workingDaysOnly: true, // Только рабочие дни
directionFuture: true // В будущее
)Находит следующий рабочий день после указанной даты.
let nextWorkingDay = nextWorkingAfter(Date())Простой подсчёт календарных дней между двумя датами.
let days = daysBetween(startDate: startDate, endDate: endDate)dateTimeString(from unixTime: Int) -> String-"2024-01-01 12:00:00"dateString(from unixTime: Int) -> String- Короткая датаtimeString(from unixTime: Int) -> String- Только время
safeDateFrom(stringDate: String?) -> Date- Безопасное получение датыdateFromServerString(stringDate: String?) -> Date?- Из формата"yyyy-MM-dd HH:mm:ss"dateFromParserString(stringDate: String?) -> Date?- Из формата"dd.MM.yyyy"
dateOrStubFrom(serverDate: String?, stub: String) -> String- Дата или заглушкаdaysToday(from serverDate: String?) -> Int- Дней от серверной даты до сегодня
corrected(days: Int) -> LocalizedStringKey- Дни (день/дня/дней)correctedRU(days: Int) -> String- Дни на русскомcorrected(years: Int) -> LocalizedStringKey- Годы (год/года/лет)corrected(months: Int) -> LocalizedStringKey- Месяцы (месяц/месяца/месяцев)
Singleton для управления датами: DateManager.shared
// Проверки unix timestamp
DateManager.shared.isToday(unixTimestamp) // Сегодня?
DateManager.shared.isTodayOrYesterday(unixTimestamp) // Сегодня или вчера?
// Сравнение с датами
DateManager.shared.isStringDate(serverDate, before: date) // Раньше даты?
DateManager.shared.isStringDate(serverDate, after: date) // Позже даты?
DateManager.shared.isStringDate(serverDate, between: start, and: end) // В диапазоне?DateManager.shared.days(from: startDate, to: endDate) // Количество дней
DateManager.shared.hoursOf(date) // Часов в датеDateManager.shared.isWorking(date) // Рабочий день? (пн-пт)
DateManager.shared.isRealWorking(date) // Реальный рабочий день с учётом праздниковDateManager.shared.nextAfter(date, days: 5) // Через 5 дней
DateManager.shared.nextAfter(date, months: 2) // Через 2 месяца
DateManager.shared.nextAfter(date, years: 1) // Через год
DateManager.shared.nextAfter(date, weeks: 3) // Через 3 неделиDateManager.shared.dateFromShort("25.12.2024", time: "14:30") // Дата из строки
DateManager.shared.daysText(date) // Текстовое представление периода
DateManager.shared.yearMonthsText(startDate: start, endDate: end) // Период в годах/месяцахSingleton с данными о праздниках: HolidayData.shared
Массив всех специальных дней (праздники, переносы) с 2015 по 2026 год.
struct SpecialDay {
let stringDate: String // "yyyy-MM-dd"
let isWorking: Bool // true = рабочий, false = выходной
}Удобные свойства и методы для работы с датами.
date.weekStart // Начало недели
date.weekEnd // Конец недели
date.monthStart // Начало месяца
date.monthEnd // Конец месяца
date.yearStart // Начало года
date.yearEnd // Конец годаdate.dayInt // День месяца (1-31)
date.monthInt // Месяц (1-12)
date.yearInt // Годdate.shortFormat // "25.12.2024"
date.shortFormatHM // "25.12.2024 14:30"
date.serverFormat // "2024-12-25 14:30:00"
date.shortServerFormat // "2024-12-25"
date.logFormat // "14:30:00"date.unixFormat // Int timestamp
date.todayUnixFormat // Timestamp на сегодняdate.isToday // Сегодня?
date.isBeforeToday // Раньше сегодня?
date.isWorking // Рабочий день? (пн-пт)
date.isTodayOrTomorrow // Сегодня или завтра?
date.isTodayOrYesterday // Сегодня или вчера?date.nextDay // Следующий день
date.dayBefore // Предыдущий день
date.startOfDay // Начало дня (00:00)
date.endOfDay // Конец дня (23:59)
date.zeroHours // Дата без времениdate.byAdding(5) // +5 дней
date.byAddingMonths(2) // +2 месяца
date.byAddingYears(1) // +1 год
date.byAddingMinutes(90) // +90 минутМодуль числа (абсолютное значение).
let positive = (-5).absolute // 5
let stillPositive = 10.absolute // 10Точка данных для календаря (id, date, value).
Юридические события с типичными сроками.
struct LegalEvent {
let title: String // Название события
let label: String // Срок (например, "1 месяц")
let months: Int
let days: Int
}Предопределённые юридические события:
- "Вынесено решение суда" (1 месяц)
- "Вынесено определение об обеспечительных мерах" (15 рабочих дней)
- "Вынесено апелляционное определение суда" (3 месяца)
- "Вынесено кассационное определение суда" (3 месяца)
Перечисление периодов истечения срока.
enum ExpirationPeriod: Int {
case year // Через год
case halfYear // Через полгода
case quarter // Через квартал
case month // Через месяц
case halfMonth // Через полмесяца
case week // Через неделю
case days // Через дни
}// Дата подачи иска
let filingDate = Date()
// Дата истечения срока (3 года)
let expirationDate = DateManager.shared.nextAfter(filingDate, years: 3)
// Проверка, не истёк ли срок
let isExpired = DateManager.shared.isStringDate(nil, before: expirationDate)let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month], from: Date())
let startOfMonth = calendar.date(from: components)!
let endOfMonth = calendar.date(byAdding: DateComponents(month: 1, day: -1), to: startOfMonth)!
let result = daysBetweenDates(
country: "RU", region: "", subregion: "",
calendarType: "working",
startDate: startOfMonth,
endDate: endOfMonth,
includeFirstDay: true
)
print("Рабочих дней в месяце: \(result.1.count)")extension Date {
var displayFormat: String {
if self.isToday {
return "Сегодня"
} else if self.isTodayOrYesterday(Date().timeIntervalSince1970.unixFormat) {
return "Вчера"
} else {
return self.shortFormat
}
}
}func calculateDeadline(from event: LegalEvent, startDate: Date) -> Date {
var resultDate = DateManager.shared.nextAfter(startDate, months: event.months)
resultDate = DateManager.shared.nextAfter(resultDate, days: event.days)
// Если последний день выпадает на выходной, переносим на следующий рабочий
if !DateManager.shared.isRealWorking(resultDate) {
resultDate = nextWorkingAfter(resultDate)
}
return resultDate
}
// Использование
let courtDecision = legalEvents[0] // Решение суда - 1 месяц
let deadline = calculateDeadline(from: courtDecision, startDate: Date())Библиотека автоматически учитывает:
- ✅ Новогодние каникулы (1-8 января)
- ✅ Рождество Христово (7 января)
- ✅ День защитника Отечества (23 февраля)
- ✅ Международный женский день (8 марта)
- ✅ Праздник Весны и Труда (1 мая)
- ✅ День Победы (9 мая)
- ✅ День России (12 июня)
- ✅ День народного единства (4 ноября)
- ✅ Все переносы выходных дней по постановлениям правительства
Автоматическая локализация для русского языка:
- Правильное склонение числительных
- Локализованные строки для интерфейса
- Поддержка русской локали в форматерах дат
- iOS: 15.0+
- macOS: 13.0+
- Swift: 5.10+
- Xcode: 14.0+
swift testDateCalc доступна под лицензией MIT. Подробности в файле LICENSE.
Все issue reports, feature requests, pull requests и GitHub звёзды приветствуются!
- Fork репозиторий
- Создайте feature branch (
git checkout -b feature/AmazingFeature) - Commit изменения (
git commit -m 'Add some AmazingFeature') - Push в branch (
git push origin feature/AmazingFeature) - Откройте Pull Request
Sergei Kriukov
Если вам нравится проект, поставьте звезду! ⭐
- Подсчёт дней - Приложение для подсчёта календарных и рабочих дней
- LawMatic Стадии дела - Управление стадиями юридических дел
- Анализ бюллетеней - Анализ судебных бюллетеней
- CaseTracker - Отслеживание судебных дел
Создано с ❤️ для юридического сообщества