Get days of weeks into months

Viewed 46

For example, I want to take the day numbers of January and the week names corresponding to this day. How can I get this?

I want to show the week's names under the day numbers.

I get the days of the months with the getNumbersOfMonths function.

Part to be noted: The first day of January 2021 is Friday. The first day of February is Monday.

enter image description here

Date Provider

class DateProvider: ObservableObject {
    
    @Published var months: [String] = []
    @Published var dateData: DateType = DateType(day: "", date: "", year: "", month: "")
    
    init() {
        months = getMonths()
        dateData = getCurrentDate()
    }
    
    func getCurrentDate() -> DateType {
        let date = Date()
        var currentDate = Calendar.current
        currentDate.locale = NSLocale(localeIdentifier: "tr_TR") as Locale
        let dateString = currentDate.component(.day, from: date)
        let monthNo = currentDate.component(.month, from: date)
        let month = currentDate.monthSymbols[monthNo - 1]
        let year = currentDate.component(.year, from: date)
        let weekNo = currentDate.component(.weekday, from: date)
        let day = currentDate.weekdaySymbols[weekNo - 1]
        return DateType(day: "\(day)", date: "\(dateString)", year: "\(year)", month: "\(month)")
    }
    
    func getMonths() -> [String] {
        let formatter = DateFormatter()
        formatter.locale = NSLocale(localeIdentifier: "tr_TR") as Locale
        let monthComponents = formatter.shortMonthSymbols ?? []
        return monthComponents
    }
    
    func getNumbersOfMonths(month: Int, year: Int) -> Int {
        let dateComponents = DateComponents(year: year, month: month)
        let calendar = Calendar.current
        let date = calendar.date(from: dateComponents)!
        let range = calendar.range(of: .day, in: .month, for: date)!
        let numDays = range.count
        return numDays + 1
    }
}

ContentView

struct ContentView: View {
    @State var data: DateType = DateType(day: "", date: "", year: "", month: "")
    @ObservedObject var dateProvider: DateProvider = DateProvider()
    var body: some View {
        ScrollView {
            VStack {

                VStack {
                    Text(self.dateProvider.dateData.day)
                    Text(self.dateProvider.dateData.date)
                    Text(self.dateProvider.dateData.month)
                    Text(self.dateProvider.dateData.year)
                    
                    VStack {
                        ForEach(dateProvider.months.indices, id: \.self) { index in
                            Text("\(dateProvider.months[index])")
                            LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 7), spacing: 10) {
                                ForEach(1 ..< dateProvider.getNumbersOfMonths(month: index + 1, year: 2021)) { item in
                                    Text("\(item)")
                                }
                            }
                            .padding(.vertical)
                        }
                    }
                }
                
            }
        }
    }
}

Model

struct DateType {
    var day: String
    var date: String
    var year: String
    var month: String
}
1 Answers

To get the weekday abbreviation, like "Mon," you need to first get a Date consisting of the year, month, and day components.

  • Get year from self.dateProvider.dateData.year
  • Get month from index in the first loop (ForEach(dateProvider.months.indices...)
  • Get day from item in the second loop (ForEach(1 ..< dateProvider.getNumbersOfMonths...)

Then, add this function to your DateProvider class. This assembles a date from year, month, and day, then returns the weekday abbreviation.

func getWeekday(year: Int, month: Int, day: Int) -> String {
    
    var components = DateComponents()
    components.year = year
    components.month = month
    components.day = day
    
    let formatter = DateFormatter()
    formatter.dateFormat = "E" /// see https://nsdateformatter.com/
    
    if let date = Calendar.current.date(from: components) {
        let string = formatter.string(from: date)
        return string
    }
    
    return "Mon"
}

Finally, call the getWeekday function, passing in the date components.

ForEach(1 ..< dateProvider.getNumbersOfMonths(month: index + 1, year: 2021)) { item in
    VStack {
        Text("\(item)")
        
        /// display weekday!
        Text("\(dateProvider.getWeekday(year: Int(dateProvider.dateData.year) ?? 2021, month: index, day: item))")
            .foregroundColor(.red)
            .font(.system(size: 12))
    }
}

Result:

Red weekday abbreviation under each date
Related