Вычислить возраст из строки swift

Я пытаюсь рассчитать возраст любого человека, начиная от младенцев и заканчивая взрослыми (например, 8 недель, 4 месяца или 22 года). Но мои расчеты отключены, и я не могу найти, где. Если я ввожу DOB как 16.10.2020, он возвращает 8 недель, что правильно. Однако, если я введу 26.10.2020, он вернет 11 недель, и это неверно. Буду признателен за любую оказанную помощь.

Возраст Функция:

let bornOn = "10/16/2020"
func calculateAge(dob: String, format: String = "MM/dd/yyyy") -> String{
    let df = DateFormatter()
    df.dateFormat = format
    let date = df.date(from: dob)
    guard let val = date else{
        return ""
    }
    var years = 0
    var months = 0
    var days = 0
    
    let cal = Calendar.current
    years = cal.component(.year, from: Date()) - cal.component(.year, from: val)
    
    let currentMonth = cal.component(.month, from: Date())
    let birthMonth = cal.component(.month, from: val)
    
    months = currentMonth - birthMonth
    
    if months < 0 {
        years = years - 1
        months = 12 - birthMonth
        if cal.component(.day, from: Date()) < cal.component(.day, from: val){
            months = months - 1
        }
    }else if months == 0 && cal.component(.day, from: Date()) < cal.component(.day, from: val){
        years = years - 1
        months = 11
    }
    if cal.component(.day, from: Date()) > cal.component(.day, from: val){
        days = cal.component(.day, from: Date()) - cal.component(.day, from: val)
    }else if cal.component(.day, from: Date()) < cal.component(.day, from: val){
        let today = cal.component(.day, from: Date())
        let date = cal.date(byAdding: .month, value: -1, to: Date())
        days = date!.daysInMonth - cal.component(.day, from: val) + today
    }else{
        days = 0
        if months == 12 {
            years = years + 1
            months = 0
        }
    }
    print("Years: \(years), Months: \(months), Days: \(days)")
    if years > 0{
        if years == 1{
            return "\(years) year old"
        }else{
        return "\(years) years old"
        }
    }else if months > 4{
        return "\(months) months old"
    }else {
        if  months >= 1{
            let daysleftInMonth = months * 30
            print(daysleftInMonth)
            days += daysleftInMonth
        }
       
        let weeks = days / 7
       return "\(weeks) weeks old"
    }
}

extension Date{
     var daysInMonth:Int{
        let calendar = Calendar.current
        
        let dateComponents = DateComponents(year: calendar.component(.year, from: self), month: calendar.component(.month, from: self))
        let date = calendar.date(from: dateComponents)!
        
        let range = calendar.range(of: .day, in: .month, for: date)!
        let numDays = range.count
        
        return numDays
    }
}
calculateAge(dob: bornOn)
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
349
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы идете в неправильном направлении. Что вам нужно, так это проанализировать строку даты, преобразовав ее в дату, и использовать DateComponentsFormatter для отображения возраста человека. Вы также можете получить компоненты даты от даты дня рождения до сегодняшнего дня:

extension Formatter {
    static let dateMMddyyyy: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = .init(identifier: "en_US_POSIX")
        formatter.dateFormat = "MM/dd/yyyy"
        return formatter
    }()
    static let dateComponents: DateComponentsFormatter = {
        let formatter = DateComponentsFormatter()
        formatter.unitsStyle = .full
        formatter.allowedUnits = [.day, .month, .year]
        formatter.maximumUnitCount = 1
        return formatter
    }()
}

extension Date {
    var ageComponents: DateComponents { Calendar.current.dateComponents([.year, .month, .day], from: self, to: Date()) }
    var relativeAge: String {
        Formatter.dateComponents.allowedUnits = ageComponents.month! >= 2 ?
            [.day, .month, .year] : [.weekOfMonth]
        return Formatter.dateComponents.string(from: self, to: Date())! 
    }
}

extension String {
    var dateFromMMddyyyy: Date? { Formatter.dateMMddyyyy.date(from: self) }
}

"09/10/1970".dateFromMMddyyyy?.relativeAge  // "50 years"
"10/16/2020".dateFromMMddyyyy?.relativeAge  // "2 months"
"10/23/2020".dateFromMMddyyyy?.relativeAge  // "7 weeks"

Я думаю, что у OP есть некоторая пользовательская логика, когда отображать недели (менее 4 месяцев), но, тем не менее, это хороший совет.

Sweeper 17.12.2020 06:14
extension Date {
    func timeAgo() -> String {
        let formatter = DateComponentsFormatter()
        formatter.unitsStyle = .full
        formatter.allowedUnits = [.year, .month, .weekOfMonth ,.day, .hour, .minute, .second]
        formatter.zeroFormattingBehavior = .dropAll
        formatter.maximumUnitCount = 1
        return String(format: formatter.string(from: self, to: Date()) ?? "", locale: .current)
    }
}

Используйте вышеуказанное расширение даты в своем методе

func calculateAge(dob: String, format: String = "MM/dd/yyyy") -> String{
       let df = DateFormatter()
       df.dateFormat = format
       let date = df.date(from: dob)
       return date?.timeAgo() ?? ""
}

Используйте это как,

let date = calculateAge(dob: bornOn)
print(date) //print - 2 weeks

Другие вопросы по теме