Разделить две даты из одной строки Swift

#arrays #swift #dateformatter

#массивы #swift #dateformatter

Вопрос:

У меня есть кнопка, которая, когда пользователь нажимает на нее, сохраняет дату события в своем календаре, используя дату начала и дату окончания события.

Эта дата начала и дата окончания загружаются из ответа json, но обе даты получены в одной строке.

Формат, который я получаю для ответа, выглядит следующим образом:

 {
   "events":[
      {
         "date":"5/12/2021 - 5/14/2021",
      },
      {
         "date":"6/22/2021 - 6/25/2021",
      }
       ]
}
  

Чтобы правильно сохранить в календаре, мне нужно отделить начальную и конечную даты от строк, отформатированных следующим образом: «ММ / ДД / ГГГГ — ММ / ДД / ГГГГ», чтобы первая дата в строке была переменной с именем StartDate, а вторая дата — переменной с именем EndDate .

Я могу проанализировать ответ json, и кнопка работает нормально, если я жестко запрограммирую два «фиктивных» массива, но как мне разделить ответ на две отдельные переменные даты, как только я получу это «ММ / ДД / ГГГГ — ММ / ДД / ГГГГ»?

Комментарии:

1. Реализуйте init(from decoder : Decoder) и добавьте логику для разделения String на две Date

2. Я могу проанализировать ответ json, но как мне разделить дату, как только я получу это «ММ / ДД / ГГГГ — ММ / ДД / ГГГГ»?

3. Вы не можете с помощью DateFormatter, у вас есть две даты, поэтому вам нужно сначала разделить строку на 2 строки, представляющие 2 даты, а затем для каждой использовать DateFormatter

Ответ №1:

Это должно сработать для вас:

 struct Response: Codable {
    let events: [Event]
}

struct Event: Codable {
    let date: String
    
    let startDate: Date
    let endDate: Date
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        date = try container.decode(String.self, forKey: .date)
        
        let splitted = date.components(separatedBy: " - ")
        
        guard let startDateString = splitted.first,
              let endDateString = splitted.last else {
            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "'date' should follow the format 'DATE1 - DATE2'"))
        }
            
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "M/dd/yyyy"
            
        guard let extractedStartDate = formatter.date(from: startDateString),
              let extractedEndDate = formatter.date(from: endDateString) else {
            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The provided dates are not in the correct format M/dd/yyyy"))
        }
        startDate = extractedStartDate
        endDate = extractedEndDate
    }
}
  

И пример синтаксического анализа из вашего json:

 let json = """
{
   "events":[
      {
         "date":"5/12/2021 - 5/14/2021",
      },
      {
         "date":"6/22/2021 - 6/25/2021",
      }
       ]
}
"""

let response = try JSONDecoder().decode(Response.self, from: json.data(using: .utf8)!)
print(response.events)
  

Комментарии:

1. Я думаю, было бы разумнее сделать свойства даты необязательными, чем принудительно разворачивать столько раз

2. Поскольку событие не имело бы смысла без дат и инициализации (декодера), я предпочел сделать его аварийным с принудительным развертыванием

3. Если сделать их необязательными, вызывающему коду придется решать, что делать, когда дата равна нулю, «сделать ее аварийной» — действительно плохая привычка.

4. Лучше выбросить DecodingError

5. Хорошо, я редактирую это прямо сейчас, я думаю, вы всегда чему-то учитесь