Я пытаюсь рассчитать возраст любого человека, начиная от младенцев и заканчивая взрослыми (например, 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)
Вы идете в неправильном направлении. Что вам нужно, так это проанализировать строку даты, преобразовав ее в дату, и использовать 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"
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
Я думаю, что у OP есть некоторая пользовательская логика, когда отображать недели (менее 4 месяцев), но, тем не менее, это хороший совет.