where query in daterange in rails with postgresql - ruby-on-rails
How to use where queries with daterange in postgresql with Rails 4.2:
ConsultingLocation Load (0.6ms) SELECT "consulting_locations".* FROM "consulting_locations" WHERE "consulting_locations"."deleted_at" IS NULL AND "consulting_locations"."id" = $1 LIMIT 1 [["id", 495]]
ConsultingLocationDoctorSchedule Load (1.7ms) SELECT "consulting_location_doctor_schedules".* FROM "consulting_location_doctor_schedules" INNER JOIN "consulting_location_doctors" ON "consulting_location_doctor_schedules"."consulting_location_doctor_id" = "consulting_location_doctors"."id" WHERE "consulting_location_doctors"."deleted_at" IS NULL AND "consulting_location_doctors"."consulting_location_id" = $1 [["consulting_location_id", 495]]
=> [#<ConsultingLocationDoctorSchedule:0x007fe7653f7538
id: 1,
consulting_location_doctor_id: 495,
schedule_date: Mon, 05 Jan 2015 00:00:00 IST +05:30,
slot_details:
[{"end"=>"2015-01-05T03:00:00.000+00:00", "start"=>"2015-01-05T02:30:00.000+00:00", "title"=>" 2:30 am to 3:00 am", "appointment_id"=>""},
{"end"=>"2015-01-05T03:30:00.000+00:00", "start"=>"2015-01-05T03:00:00.000+00:00", "title"=>" 3:00 am to 3:30 am", "appointment_id"=>""},
{"end"=>"2015-01-05T04:00:00.000+00:00", "start"=>"2015-01-05T03:30:00.000+00:00", "title"=>" 3:30 am to 4:00 am", "appointment_id"=>""},
{"end"=>"2015-01-05T04:30:00.000+00:00", "start"=>"2015-01-05T04:00:00.000+00:00", "title"=>" 4:00 am to 4:30 am", "appointment_id"=>""},
{"end"=>"2015-01-05T05:00:00.000+00:00", "start"=>"2015-01-05T04:30:00.000+00:00", "title"=>" 4:30 am to 5:00 am", "appointment_id"=>""},
{"end"=>"2015-01-05T05:30:00.000+00:00", "start"=>"2015-01-05T05:00:00.000+00:00", "title"=>" 5:00 am to 5:30 am", "appointment_id"=>""},
{"end"=>"2015-01-05T06:00:00.000+00:00", "start"=>"2015-01-05T05:30:00.000+00:00", "title"=>" 5:30 am to 6:00 am", "appointment_id"=>""},
{"end"=>"2015-01-05T06:30:00.000+00:00", "start"=>"2015-01-05T06:00:00.000+00:00", "title"=>" 6:00 am to 6:30 am", "appointment_id"=>""},
{"end"=>"2015-01-05T07:00:00.000+00:00", "start"=>"2015-01-05T06:30:00.000+00:00", "title"=>" 6:30 am to 7:00 am", "appointment_id"=>""},
{"end"=>"2015-01-05T07:30:00.000+00:00", "start"=>"2015-01-05T07:00:00.000+00:00", "title"=>" 7:00 am to 7:30 am", "appointment_id"=>""},
{"end"=>"2015-01-05T08:00:00.000+00:00", "start"=>"2015-01-05T07:30:00.000+00:00", "title"=>" 7:30 am to 8:00 am", "appointment_id"=>""},
{"end"=>"2015-01-05T08:30:00.000+00:00", "start"=>"2015-01-05T08:00:00.000+00:00", "title"=>" 8:00 am to 8:30 am", "appointment_id"=>""},
{"end"=>"2015-01-05T09:00:00.000+00:00", "start"=>"2015-01-05T08:30:00.000+00:00", "title"=>" 8:30 am to 9:00 am", "appointment_id"=>""},
{"end"=>"2015-01-05T09:30:00.000+00:00", "start"=>"2015-01-05T09:00:00.000+00:00", "title"=>" 9:00 am to 9:30 am", "appointment_id"=>""},
{"end"=>"2015-01-05T10:00:00.000+00:00", "start"=>"2015-01-05T09:30:00.000+00:00", "title"=>" 9:30 am to 10:00 am", "appointment_id"=>""},
{"end"=>"2015-01-05T10:30:00.000+00:00", "start"=>"2015-01-05T10:00:00.000+00:00", "title"=>"10:00 am to 10:30 am", "appointment_id"=>""},
{"end"=>"2015-01-05T11:00:00.000+00:00", "start"=>"2015-01-05T10:30:00.000+00:00", "title"=>"10:30 am to 11:00 am", "appointment_id"=>""},
{"end"=>"2015-01-05T11:30:00.000+00:00", "start"=>"2015-01-05T11:00:00.000+00:00", "title"=>"11:00 am to 11:30 am", "appointment_id"=>""},
{"end"=>"2015-01-05T12:00:00.000+00:00", "start"=>"2015-01-05T11:30:00.000+00:00", "title"=>"11:30 am to 12:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T12:30:00.000+00:00", "start"=>"2015-01-05T12:00:00.000+00:00", "title"=>"12:00 pm to 12:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T13:00:00.000+00:00", "start"=>"2015-01-05T12:30:00.000+00:00", "title"=>"12:30 pm to 1:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T13:30:00.000+00:00", "start"=>"2015-01-05T13:00:00.000+00:00", "title"=>" 1:00 pm to 1:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T14:00:00.000+00:00", "start"=>"2015-01-05T13:30:00.000+00:00", "title"=>" 1:30 pm to 2:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T14:30:00.000+00:00", "start"=>"2015-01-05T14:00:00.000+00:00", "title"=>" 2:00 pm to 2:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T15:00:00.000+00:00", "start"=>"2015-01-05T14:30:00.000+00:00", "title"=>" 2:30 pm to 3:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T15:30:00.000+00:00", "start"=>"2015-01-05T15:00:00.000+00:00", "title"=>" 3:00 pm to 3:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T16:00:00.000+00:00", "start"=>"2015-01-05T15:30:00.000+00:00", "title"=>" 3:30 pm to 4:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T16:30:00.000+00:00", "start"=>"2015-01-05T16:00:00.000+00:00", "title"=>" 4:00 pm to 4:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T17:00:00.000+00:00", "start"=>"2015-01-05T16:30:00.000+00:00", "title"=>" 4:30 pm to 5:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T17:30:00.000+00:00", "start"=>"2015-01-05T17:00:00.000+00:00", "title"=>" 5:00 pm to 5:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T18:00:00.000+00:00", "start"=>"2015-01-05T17:30:00.000+00:00", "title"=>" 5:30 pm to 6:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T18:30:00.000+00:00", "start"=>"2015-01-05T18:00:00.000+00:00", "title"=>" 6:00 pm to 6:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T19:00:00.000+00:00", "start"=>"2015-01-05T18:30:00.000+00:00", "title"=>" 6:30 pm to 7:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-05T19:30:00.000+00:00", "start"=>"2015-01-05T19:00:00.000+00:00", "title"=>" 7:00 pm to 7:30 pm", "appointment_id"=>""}],
start_and_end_time: Mon, 05 Jan 2015...Tue, 06 Jan 2015,
deleted_at: nil,
deleted_by_id: nil,
created_at: Wed, 31 Dec 2014 16:21:59 IST +05:30,
updated_at: Wed, 31 Dec 2014 16:21:59 IST +05:30>,
#<ConsultingLocationDoctorSchedule:0x007fe7653f7380
id: 2,
consulting_location_doctor_id: 495,
schedule_date: Tue, 06 Jan 2015 00:00:00 IST +05:30,
slot_details:
[{"end"=>"2015-01-06T09:30:00.000+00:00", "start"=>"2015-01-06T09:00:00.000+00:00", "title"=>" 9:00 am to 9:30 am", "appointment_id"=>""},
{"end"=>"2015-01-06T10:00:00.000+00:00", "start"=>"2015-01-06T09:30:00.000+00:00", "title"=>" 9:30 am to 10:00 am", "appointment_id"=>""},
{"end"=>"2015-01-06T10:30:00.000+00:00", "start"=>"2015-01-06T10:00:00.000+00:00", "title"=>"10:00 am to 10:30 am", "appointment_id"=>""},
{"end"=>"2015-01-06T11:00:00.000+00:00", "start"=>"2015-01-06T10:30:00.000+00:00", "title"=>"10:30 am to 11:00 am", "appointment_id"=>""},
{"end"=>"2015-01-06T11:30:00.000+00:00", "start"=>"2015-01-06T11:00:00.000+00:00", "title"=>"11:00 am to 11:30 am", "appointment_id"=>""},
{"end"=>"2015-01-06T12:00:00.000+00:00", "start"=>"2015-01-06T11:30:00.000+00:00", "title"=>"11:30 am to 12:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T12:30:00.000+00:00", "start"=>"2015-01-06T12:00:00.000+00:00", "title"=>"12:00 pm to 12:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T13:00:00.000+00:00", "start"=>"2015-01-06T12:30:00.000+00:00", "title"=>"12:30 pm to 1:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T13:30:00.000+00:00", "start"=>"2015-01-06T13:00:00.000+00:00", "title"=>" 1:00 pm to 1:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T14:00:00.000+00:00", "start"=>"2015-01-06T13:30:00.000+00:00", "title"=>" 1:30 pm to 2:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T14:30:00.000+00:00", "start"=>"2015-01-06T14:00:00.000+00:00", "title"=>" 2:00 pm to 2:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T15:00:00.000+00:00", "start"=>"2015-01-06T14:30:00.000+00:00", "title"=>" 2:30 pm to 3:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T15:30:00.000+00:00", "start"=>"2015-01-06T15:00:00.000+00:00", "title"=>" 3:00 pm to 3:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T16:00:00.000+00:00", "start"=>"2015-01-06T15:30:00.000+00:00", "title"=>" 3:30 pm to 4:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T16:30:00.000+00:00", "start"=>"2015-01-06T16:00:00.000+00:00", "title"=>" 4:00 pm to 4:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T17:00:00.000+00:00", "start"=>"2015-01-06T16:30:00.000+00:00", "title"=>" 4:30 pm to 5:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T17:30:00.000+00:00", "start"=>"2015-01-06T17:00:00.000+00:00", "title"=>" 5:00 pm to 5:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T18:00:00.000+00:00", "start"=>"2015-01-06T17:30:00.000+00:00", "title"=>" 5:30 pm to 6:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T18:30:00.000+00:00", "start"=>"2015-01-06T18:00:00.000+00:00", "title"=>" 6:00 pm to 6:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T19:00:00.000+00:00", "start"=>"2015-01-06T18:30:00.000+00:00", "title"=>" 6:30 pm to 7:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T19:30:00.000+00:00", "start"=>"2015-01-06T19:00:00.000+00:00", "title"=>" 7:00 pm to 7:30 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T20:00:00.000+00:00", "start"=>"2015-01-06T19:30:00.000+00:00", "title"=>" 7:30 pm to 8:00 pm", "appointment_id"=>""},
{"end"=>"2015-01-06T20:30:00.000+00:00", "start"=>"2015-01-06T20:00:00.000+00:00", "title"=>" 8:00 pm to 8:30 pm", "appointment_id"=>""}],
start_and_end_time: Tue, 06 Jan 2015...Wed, 07 Jan 2015,
deleted_at: nil,
deleted_by_id: nil,
created_at: Wed, 31 Dec 2014 16:21:59 IST +05:30,
updated_at: Wed, 31 Dec 2014 16:21:59 IST +05:30>,
Usually with simple date we would do Table.where(start_and_end_time: Date.yesterday..Date.today)
I tried :
where("start_and_end_time :#> ?",Date.yesterday..Date.today)
threw this error:
ConsultingLocation.find(495).schedules.where("start_and_end_time :#> ?",Date.yesterday..Date.today)
ConsultingLocation Load (0.5ms) SELECT "consulting_locations".* FROM "consulting_locations" WHERE "consulting_locations"."deleted_at" IS NULL AND "consulting_locations"."id" = $1 LIMIT 1 [["id", 495]]
PG::SyntaxError: ERROR: syntax error at or near ":"
LINE 1: ...sulting_location_id" = $1 AND (start_and_end_time :#> '2014-...
and it did not work. How to work with dateranges in general
This also did not work:
ConsultingLocation.find(495).schedules.where(start_and_end_time: Date.yesterday..Date.today)
ConsultingLocation Load (103.0ms) SELECT "consulting_locations".* FROM "consulting_locations" WHERE "consulting_locations"."deleted_at" IS NULL AND "consulting_locations"."id" = $1 LIMIT 1 [["id", 495]]
PG::InvalidTextRepresentation: ERROR: malformed range literal: "2015-01-01"
LINE 1: ...on_doctor_schedules"."start_and_end_time" BETWEEN '2015-01-0...
^
DETAIL: Missing left parenthesis or bracket.
If you want to determine if a range contains another range:
where("start_and_end_time && daterange(?, ?, '[]')", Date.yesterday, Date.today)
If you want to know if a date falls within a range:
where("start_and_end_time #> ?::date", Date.yesterday)
I found these articles helpful:
https://wiki.postgresql.org/images/7/73/Range-types-pgopen-2012.pdf
https://wiki.postgresql.org/wiki/RangeTypes
http://edgeguides.rubyonrails.org/active_record_postgresql.html#range-types
https://www.postgresql.org/docs/9.3/static/rangetypes.html
Related
How to use DateComponents to represent the extra 1 hour period at the end of day light saving?
Usually, during end of day light saving, we will be gaining extra 1 hours. Take Tehran timezone as an example. During 22 September 2021, Tehran will backward by 1 hour from 00:00 AM, to 11:00 PM. I wrote the following code to demonstrate such. import UIKit func date(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int) -> Date { var dateComponents = DateComponents() dateComponents.year = year dateComponents.month = month dateComponents.day = day dateComponents.hour = hour dateComponents.minute = minute dateComponents.second = second let date = Calendar.current.date(from: dateComponents)! return date } // During 22 September 2021, Tehran will backward by 1 hour from 00:00 AM, to 11:00 PM. let tehranTimeZone = TimeZone(identifier: "Asia/Tehran")! let oldDefault = NSTimeZone.default NSTimeZone.default = tehranTimeZone defer { NSTimeZone.default = oldDefault } let date1 = date(year: 2021, month: 09, day: 21, hour: 23, minute: 59, second: 59) let date2 = date(year: 2021, month: 09, day: 22, hour: 00, minute: 00, second: 00) let date3 = date(year: 2021, month: 09, day: 22, hour: 00, minute: 00, second: 01) // STEP 1: 2021 Sep 21 23:59:59 => 1632252599.0, Tuesday, September 21, 2021 at 11:59:59 PM Iran Daylight Time print("STEP 1: 2021 Sep 21 23:59:59 => \(date1.timeIntervalSince1970), \(date1.description(with: .current))") // STEP 2: 2021 Sep 22 00:00:00 => 1632256200.0, Wednesday, September 22, 2021 at 12:00:00 AM Iran Standard Time print("STEP 2: 2021 Sep 22 00:00:00 => \(date2.timeIntervalSince1970), \(date2.description(with: .current))") // STEP 3: 2021 Sep 22 00:00:01 => 1632256201.0, Wednesday, September 22, 2021 at 12:00:01 AM Iran Standard Time print("STEP 3: 2021 Sep 22 00:00:01 => \(date3.timeIntervalSince1970), \(date3.description(with: .current))") From STEP 1 transits to STEP 2, instead for their timeIntervalSince1970 different by +1 seconds, their difference are +3601 seconds, due to the extra 1 hour gain. Now, my question is, how can we use DateComponents to represent the extra 1 hour period at the end of day light saving? In another, how can I use DateComponents to generate a Date which is capable to print the following? 2021 Sep 21 23:00:00 => 1632252600.0, Tuesday, September 21, 2021 at 11:00:00 PM Iran Standard Time Now, we understand that, in Tehran, during 2021 Sept 21, there are 2 type of 23:00:00 time 23:00:00 Iran Daylight time (Epoch is 1632249000) 23:00:00 Iran Standard time (Epoch is 1632252600) 23:00:00 Iran Daylight time (Epoch is 1632249000) I can represent the above using let date = date(year: 2021, month: 09, day: 21, hour: 23, minute: 00, second: 00) 23:00:00 Iran Standard time (Epoch is 1632252600) I have no idea how to represent the above. As, I do not find a way in DateComponents, to enable us to specific whether the local time is belong to standard time, or daylight time.
DateComponents do not have a time zone. The time zone comes into it when you convert DateComponents to a Date, using the call Calendar.date(from:). It's the calendar's time zone that determines how those DateComponents are converted to a Date. Instead of using Calendar.current, create a custom calendar and set it to the IRST time zone. (I couldn't figure out the time zone for Iran Daylight time. I would have expected it to have the abbreviation "IRDT", but that doesn't work.) Let's say we have a calendar irstCalendar that's set to Iran Standard Time ("IRST"). If you use irstCalendar.date(from: dateComponents) you'll always get the Date based on standard time. Consider this code: func date(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int, calendar: Calendar = Calendar.current) -> Date { var dateComponents = DateComponents() dateComponents.year = year dateComponents.month = month dateComponents.day = day dateComponents.hour = hour dateComponents.minute = minute dateComponents.second = second let date = calendar.date(from: dateComponents)! return date } guard let tehranStandardTimeZone = TimeZone(abbreviation: "IRST") else { fatalError("Can't create time zones") } var tehranSTCalendar = Calendar(identifier: .gregorian) tehranSTCalendar.timeZone = tehranStandardTimeZone let tehranDateFormatter = DateFormatter() tehranDateFormatter.dateStyle = .medium tehranDateFormatter.timeStyle = .medium tehranDateFormatter.timeZone = tehranStandardTimeZone let date1 = date(year: 2021, month: 09, day: 21, hour: 23, minute: 59, second: 59, calendar: tehranSTCalendar) let date2 = date(year: 2021, month: 09, day: 22, hour: 00, minute: 00, second: 00, calendar: tehranSTCalendar) let date3 = date(year: 2021, month: 09, day: 22, hour: 00, minute: 00, second: 01, calendar: tehranSTCalendar) print("STEP 1: 2021 Sep 21 23:59:59 => \(date1.timeIntervalSince1970), \(tehranDateFormatter.string(from:date1))") print("STEP 2: 2021 Sep 22 00:00:00 => \(date2.timeIntervalSince1970), \(tehranDateFormatter.string(from:date2))") print("STEP 3: 2021 Sep 22 00:00:01 => \(date3.timeIntervalSince1970), \(tehranDateFormatter.string(from:date3))") That outputs: STEP 1: 2021 Sep 21 23:59:59 => 1632252599.0, Sep 21, 2021 at 11:59:59 PM STEP 2: 2021 Sep 22 00:00:00 => 1632256200.0, Sep 22, 2021 at 12:00:00 AM STEP 3: 2021 Sep 22 00:00:01 => 1632256201.0, Sep 22, 2021 at 12:00:01 AM
Swift - Add N month to date
I have used the following code to generate dates between two dates. It works in all cases where the day of the month is less than 28. extension Date { public func addMonth(n: Int) -> Date { let calendar = Calendar.current return calendar.date(byAdding: .month, value: n, to: self)! } public func addYear(n: Int) -> Date { let calendar = Calendar.current return calendar.date(byAdding: .year, value: n, to: self)! } public var monthName: String { let calendar = Calendar.current let monthInt = calendar.component(.month, from: self) return calendar.monthSymbols[monthInt-1] } } var date = Date() repeat { date = date.addMonth(n: 1) print("\(date) \(date.monthName) ") } while date <= Date().addYear(n: 2) Result 2020-07-30 13:31:14 +0000 July 2020-08-30 13:31:14 +0000 August 2020-09-30 13:31:14 +0000 September 2020-10-30 14:31:14 +0000 October 2020-11-30 14:31:14 +0000 November 2020-12-30 14:31:14 +0000 December 2021-01-30 14:31:14 +0000 January 2021-02-28 14:31:14 +0000 February 2021-03-28 13:31:14 +0000 March 2021-04-28 13:31:14 +0000 April 2021-05-28 13:31:14 +0000 May 2021-06-28 13:31:14 +0000 June 2021-07-28 13:31:14 +0000 July 2021-08-28 13:31:14 +0000 August 2021-09-28 13:31:14 +0000 September 2021-10-28 13:31:14 +0000 October 2021-11-28 14:31:14 +0000 November 2021-12-28 14:31:14 +0000 December 2022-01-28 14:31:14 +0000 January 2022-02-28 14:31:14 +0000 February 2022-03-28 13:31:14 +0000 March 2022-04-28 13:31:14 +0000 April 2022-05-28 13:31:14 +0000 May 2022-06-28 13:31:14 +0000 June 2022-07-28 13:31:14 +0000 July Expected result I expect the result to be either 28 or 30. 2020-07-30 13:31:14 +0000 July 2020-08-30 13:31:14 +0000 August 2020-09-30 13:31:14 +0000 September 2020-10-30 14:31:14 +0000 October 2020-11-30 14:31:14 +0000 November 2020-12-30 14:31:14 +0000 December 2021-01-30 14:31:14 +0000 January 2021-02-28 14:31:14 +0000 February 2021-03-30 13:31:14 +0000 March 2021-04-30 13:31:14 +0000 April 2021-05-30 13:31:14 +0000 May 2021-06-30 13:31:14 +0000 June 2021-07-30 13:31:14 +0000 July 2021-08-30 13:31:14 +0000 August 2021-09-30 13:31:14 +0000 September 2021-10-30 13:31:14 +0000 October 2021-11-30 14:31:14 +0000 November 2021-12-30 14:31:14 +0000 December 2022-01-30 14:31:14 +0000 January 2022-02-28 14:31:14 +0000 February 2022-03-30 13:31:14 +0000 March 2022-04-30 13:31:14 +0000 April 2022-05-30 13:31:14 +0000 May 2022-06-30 13:31:14 +0000 June 2022-07-30 13:31:14 +0000 July Does Calendar has built-in functionality to achieve this?
As you observed, adding 1 month n times is not the same as adding n month. Apparently you want the latter, e.g. like this: let now = Date() let finalDate = now.addYear(n: 2) for n in 1... { let date = now.addMonth(n: n) print("\(date) \(date.monthName) ") if date > finalDate { break } } Or this: let now = Date() let finalDate = now.addYear(n: 2) let dates = (1...).lazy.map { now.addMonth(n: $0) } .prefix(while: { $0 <= finalDate } ) for date in dates { print("\(date) \(date.monthName)") }
You can use Calendar method nextDate(after:) passing previousTimePreservingSmallerComponents as the matchingPolicy: public extension Date { func noon(using calendar: Calendar = .current) -> Date { calendar.date(bySettingHour: 12, minute: 0, second: 0, of: self)! } func day(using calendar: Calendar = .current) -> Int { calendar.component(.day, from: self) } func adding(_ component: Calendar.Component, value: Int, using calendar: Calendar = .current) -> Date { calendar.date(byAdding: component, value: value, to: self)! } func monthSymbol(using calendar: Calendar = .current) -> String { calendar.monthSymbols[calendar.component(.month, from: self)-1] } } var date = Date().noon() // "Jun 30, 2020 at 12:00 PM" let day = date.day() let endDate = date.adding(.year, value: 2) repeat { date = Calendar.current.nextDate(after: date, matching: DateComponents(day: day, hour: 12), matchingPolicy: .previousTimePreservingSmallerComponents)! print(date.description(with: .current), date.monthSymbol()) } while date <= endDate this will print: Thursday, July 30, 2020 at 12:00:00 PM Brasilia Standard Time July Sunday, August 30, 2020 at 12:00:00 PM Brasilia Standard Time August Wednesday, September 30, 2020 at 12:00:00 PM Brasilia Standard Time September Friday, October 30, 2020 at 12:00:00 PM Brasilia Standard Time October Monday, November 30, 2020 at 12:00:00 PM Brasilia Standard Time November Wednesday, December 30, 2020 at 12:00:00 PM Brasilia Standard Time December Saturday, January 30, 2021 at 12:00:00 PM Brasilia Standard Time January Sunday, February 28, 2021 at 12:00:00 PM Brasilia Standard Time February Tuesday, March 30, 2021 at 12:00:00 PM Brasilia Standard Time March Friday, April 30, 2021 at 12:00:00 PM Brasilia Standard Time April Sunday, May 30, 2021 at 12:00:00 PM Brasilia Standard Time May Wednesday, June 30, 2021 at 12:00:00 PM Brasilia Standard Time June Friday, July 30, 2021 at 12:00:00 PM Brasilia Standard Time July Monday, August 30, 2021 at 12:00:00 PM Brasilia Standard Time August Thursday, September 30, 2021 at 12:00:00 PM Brasilia Standard Time September Saturday, October 30, 2021 at 12:00:00 PM Brasilia Standard Time October Tuesday, November 30, 2021 at 12:00:00 PM Brasilia Standard Time November Thursday, December 30, 2021 at 12:00:00 PM Brasilia Standard Time December Sunday, January 30, 2022 at 12:00:00 PM Brasilia Standard Time January Monday, February 28, 2022 at 12:00:00 PM Brasilia Standard Time February Wednesday, March 30, 2022 at 12:00:00 PM Brasilia Standard Time March Saturday, April 30, 2022 at 12:00:00 PM Brasilia Standard Time April Monday, May 30, 2022 at 12:00:00 PM Brasilia Standard Time May Thursday, June 30, 2022 at 12:00:00 PM Brasilia Standard Time June Saturday, July 30, 2022 at 12:00:00 PM Brasilia Standard Time July edit/update: If you need every nth month: var date = Date().noon() // "Jun 30, 2020 at 12:00 PM" let day = date.day() let endDate = date.adding(.year, value: 2) var dates: [Date] = [] let nthMonth = 3 var counter = 0 repeat { counter += 1 date = Calendar.current.nextDate(after: date, matching: DateComponents(day: day, hour: 12), matchingPolicy: .previousTimePreservingSmallerComponents)! if counter.isMultiple(of: nthMonth) { dates.append(date) print(date.description(with: .current), date.monthSymbol()) } } while date <= endDate This will print: Wednesday, September 30, 2020 at 12:00:00 PM Brasilia Standard Time September Wednesday, December 30, 2020 at 12:00:00 PM Brasilia Standard Time December Tuesday, March 30, 2021 at 12:00:00 PM Brasilia Standard Time March Wednesday, June 30, 2021 at 12:00:00 PM Brasilia Standard Time June Thursday, September 30, 2021 at 12:00:00 PM Brasilia Standard Time September Thursday, December 30, 2021 at 12:00:00 PM Brasilia Standard Time December Wednesday, March 30, 2022 at 12:00:00 PM Brasilia Standard Time March Thursday, June 30, 2022 at 12:00:00 PM Brasilia Standard Time June
Split last two hours in 10 minutes slices
I am trying to get every 10 minutes of the last hour. For example, now is 15:46:41 I want [15:40:00, 15:30:00, 15:20:00, 15:10:00, 15:00:00, 14:50:00, 14:40:00, 14:30:00, 14:20:00, 14:10:00, 14:00:00, 13:50:00, 13:40:00] let calendar = Calendar.current let now = Date() var components = DateComponents() components.hour = -2 if let early = calendar.date(byAdding: components, to: now) { let nowMin = calendar.component(.minute, from: early) let diff = 10 - (nowMin % 10) components.minute = diff var minutes: [Int] = [] for _ in 0...13 { // I cant figure out what should I do next. } print(minutes) }
You can get now's minute, get the remainder of this value divided by ten and subtract it from that value. This way you get the last tenth hour minute, then you just need to set it with the same hour component to now to find out the first element of your array. Next you can fill the rest of dates subtracting 10 minutes times the element position from the start date. Try like this: Xcode 11 • Swift 5.1 (for older versions just add the return statement as usual) extension Date { var hour: Int { Calendar.current.component(.hour, from: self) } var minute: Int { Calendar.current.component(.minute, from: self) } var previousHourTenth: Date { Calendar.current.date(bySettingHour: hour, minute: minute - minute % 10, second: 0, of: self)! } func lastNthHourTenth(n: Int) -> [Date] { (0..<n).map { Calendar.current.date(byAdding: .minute, value: -10*$0, to: previousHourTenth)! } } } Playground testing Date() // "Sep 25, 2019 at 10:19 AM" Date().previousHourTenth // "Sep 25, 2019 at 10:10 AM" Date().lastNthHourTenth(n: 13) // "Sep 25, 2019 at 10:10 AM", "Sep 25, 2019 at 10:00 AM", "Sep 25, 2019 at 9:50 AM", "Sep 25, 2019 at 9:40 AM", "Sep 25, 2019 at 9:30 AM", "Sep 25, 2019 at 9:20 AM", "Sep 25, 2019 at 9:10 AM", "Sep 25, 2019 at 9:00 AM", "Sep 25, 2019 at 8:50 AM", "Sep 25, 2019 at 8:40 AM", "Sep 25, 2019 at 8:30 AM", "Sep 25, 2019 at 8:20 AM", "Sep 25, 2019 at 8:10 AM"] Now you just need to use DateFormatter to display those dates as needed to the user.
Use where queries in JSONB datatype in Rails Postgres
How to query out schedules who has slot_details which have empty appointment_id. Here is an example data set: id: 98, consulting_location_doctor_id: 498, schedule_date: Thu, 15 Jan 2015 00:00:00 IST +05:30, slot_details: [{"end"=>"2015-01-15T15:00:00.000+00:00", "start"=>"2015-01-15T14:30:00.000+00:00", "title"=>" 2:30 pm to 3:00 pm", appointment_id: ""}, {"end"=>"2015-01-15T15:30:00.000+00:00", "start"=>"2015-01-15T15:00:00.000+00:00", "title"=>" 3:00 pm to 3:30 pm", appointment_id: ""}, {"end"=>"2015-01-15T16:00:00.000+00:00", "start"=>"2015-01-15T15:30:00.000+00:00", "title"=>" 3:30 pm to 4:00 pm", appointment_id: ""}, {"end"=>"2015-01-15T16:30:00.000+00:00", "start"=>"2015-01-15T16:00:00.000+00:00", "title"=>" 4:00 pm to 4:30 pm", appointment_id: ""}, {"end"=>"2015-01-15T17:00:00.000+00:00", "start"=>"2015-01-15T16:30:00.000+00:00", "title"=>" 4:30 pm to 5:00 pm", appointment_id: ""}, {"end"=>"2015-01-15T17:30:00.000+00:00", "start"=>"2015-01-15T17:00:00.000+00:00", "title"=>" 5:00 pm to 5:30 pm", appointment_id: ""}, {"end"=>"2015-01-15T18:00:00.000+00:00", "start"=>"2015-01-15T17:30:00.000+00:00", "title"=>" 5:30 pm to 6:00 pm", appointment_id: ""}, {"end"=>"2015-01-15T18:30:00.000+00:00", "start"=>"2015-01-15T18:00:00.000+00:00", "title"=>" 6:00 pm to 6:30 pm", appointment_id: ""}, {"end"=>"2015-01-15T19:00:00.000+00:00", "start"=>"2015-01-15T18:30:00.000+00:00", "title"=>" 6:30 pm to 7:00 pm", appointment_id: ""}, {"end"=>"2015-01-15T19:30:00.000+00:00", "start"=>"2015-01-15T19:00:00.000+00:00", "title"=>" 7:00 pm to 7:30 pm", appointment_id: ""}, {"end"=>"2015-01-15T20:00:00.000+00:00", "start"=>"2015-01-15T19:30:00.000+00:00", "title"=>" 7:30 pm to 8:00 pm", appointment_id: ""}, {"end"=>"2015-01-15T20:30:00.000+00:00", "start"=>"2015-01-15T20:00:00.000+00:00", "title"=>" 8:00 pm to 8:30 pm", appointment_id: ""}, {"end"=>"2015-01-15T21:00:00.000+00:00", "start"=>"2015-01-15T20:30:00.000+00:00", "title"=>" 8:30 pm to 9:00 pm", appointment_id: ""}, {"end"=>"2015-01-15T21:30:00.000+00:00", "start"=>"2015-01-15T21:00:00.000+00:00", "title"=>" 9:00 pm to 9:30 pm", appointment_id: ""}, {"end"=>"2015-01-15T22:00:00.000+00:00", "start"=>"2015-01-15T21:30:00.000+00:00", "title"=>" 9:30 pm to 10:00 pm", appointment_id: ""}, {"end"=>"2015-01-15T22:30:00.000+00:00", "start"=>"2015-01-15T22:00:00.000+00:00", "title"=>"10:00 pm to 10:30 pm", appointment_id: ""}, {"end"=>"2015-01-15T23:00:00.000+00:00", "start"=>"2015-01-15T22:30:00.000+00:00", "title"=>"10:30 pm to 11:00 pm", appointment_id: ""}, {"end"=>"2015-01-15T23:30:00.000+00:00", "start"=>"2015-01-15T23:00:00.000+00:00", "title"=>"11:00 pm to 11:30 pm", appointment_id: ""}, {"end"=>"2015-01-16T00:00:00.000+00:00", "start"=>"2015-01-15T23:30:00.000+00:00", "title"=>"11:30 pm to 12:00 am", appointment_id: ""}], start_and_end_time: Thu, 15 Jan 2015...Fri, 16 Jan 2015, deleted_at: nil, deleted_by_id: nil, created_at: Tue, 30 Dec 2014 04:28:06 IST +05:30, updated_at: Tue, 30 Dec 2014 04:28:06 IST +05:30> I tried the example in guides as well. There is no example for where query on array of json. Please help.
Maybe this could help you: slot -> 'slot_details' #> '[{"end"=>"2015-01-15T20:00:00.000+00:00"}]' the idea is to ask if the partial subarray contained. If you were not in an array bun in an object it would instead be (let say we have a profile object): profile -> 'basics' #> '{"name":"john"}' don't be fooled trying to use ? here instead of #>
Rails Time Select with two range
I have to show a select box which have time from 9 Am to 11 Am Then 1Pm to 3pm with 15 minutes inteveral like the following: 9:00 AM 9:15 AM 9:30 AM . . . 10:45 AM 11:00 AM 01:00 PM 01:15 PM 01:30 PM . . . 2:45 PM 3:00 PM The above mentioned range will be dynamic but it has two intervals. Hows it is possible to achieve this?
First define the boundaries, start_time = DateTime.parse("9 AM").to_i start_interval = DateTime.parse("11 AM").to_i end_interval = DateTime.parse("1 PM").to_i end_time = DateTime.parse("3 PM").to_i Then use range and select to get the desired values, values = (start_time..end_time).step(15.minutes).select{|t| t <= start_interval || t >= end_interval } Then you can iterate over these values to generate select options, for example, select_tag :dt, options_for_select(values.map{ |t| [ Time.at(t).utc.to_datetime.strftime("%H:%M %p"), Time.at(t).utc.to_datetime ] } ) You can try this in console, > (start_time..end_time).step(15.minutes).select{|t| t <= start_interval || t >= end_interval }.map{ |t| Time.at(t).utc.to_datetime.strftime("%H:%M %p") } => ["09:00 AM", "09:15 AM", "09:30 AM", "09:45 AM", "10:00 AM", "10:15 AM", "10:30 AM", "10:45 AM", "11:00 AM", "13:00 PM", "13:15 PM", "13:30 PM", "13:45 PM", "14:00 PM", "14:15 PM", "14:30 PM", "14:45 PM", "15:00 PM"]