Not able to view the last label in xaxis - highcharts

We are creating a line chart for which we are facing some issues. xaxis title is not getting populated for some last values, and this is plotted in the chart, but not been displayed in the label part. Please do help us in providing some solution for it.
Have the issue here :
http://jsfiddle.net/58jy1zhd/1/
$(function () {
$('#container').highcharts({
xAxis: {
categories: ["20-04-2015, 6:55 PM","20-04-2015, 7:00 PM","20-04-2015, 7:05 PM","20-04-2015, 7:10 PM","20-04-2015, 7:15 PM","20-04-2015, 7:20 PM","20-04-2015, 7:25 PM","20-04-2015, 7:30 PM","20-04-2015, 7:35 PM","20-04-2015, 7:40 PM","20-04-2015, 7:45 PM","20-04-2015, 7:50 PM","20-04-2015, 7:55 PM","20-04-2015, 8:00 PM","20-04-2015, 8:05 PM","20-04-2015, 8:10 PM","20-04-2015, 8:15 PM","20-04-2015, 8:20 PM","20-04-2015, 8:25 PM","20-04-2015, 8:30 PM","20-04-2015, 8:35 PM","20-04-2015, 8:40 PM","20-04-2015, 8:45 PM","20-04-2015, 8:50 PM","20-04-2015, 8:55 PM","20-04-2015, 9:00 PM","20-04-2015, 9:05 PM","20-04-2015, 9:10 PM","20-04-2015, 9:15 PM","20-04-2015, 9:20 PM","20-04-2015, 9:25 PM","20-04-2015, 9:30 PM","20-04-2015, 9:35 PM","20-04-2015, 9:40 PM","20-04-2015, 9:45 PM","20-04-2015, 9:50 PM","20-04-2015, 9:55 PM","20-04-2015, 10:00 PM","20-04-2015, 10:05 PM","20-04-2015, 10:10 PM","20-04-2015, 10:15 PM","20-04-2015, 10:20 PM","20-04-2015, 10:25 PM","20-04-2015, 10:30 PM","20-04-2015, 10:35 PM","20-04-2015, 10:40 PM","20-04-2015, 10:45 PM","20-04-2015, 10:50 PM","20-04-2015, 10:55 PM","20-04-2015, 11:00 PM","20-04-2015, 11:05 PM","20-04-2015, 11:10 PM","20-04-2015, 11:15 PM","20-04-2015, 11:20 PM","20-04-2015, 11:25 PM","20-04-2015, 11:30 PM","20-04-2015, 11:35 PM","20-04-2015, 11:40 PM","20-04-2015, 11:45 PM","20-04-2015, 11:50 PM","20-04-2015, 11:55 PM","21-04-2015, 12:00 AM","21-04-2015, 12:05 AM","21-04-2015, 12:10 AM","21-04-2015, 12:15 AM","21-04-2015, 12:20 AM","21-04-2015, 12:25 AM","21-04-2015, 12:30 AM","21-04-2015, 12:35 AM","21-04-2015, 12:40 AM","21-04-2015, 12:45 AM","21-04-2015, 12:50 AM","21-04-2015, 12:55 AM","21-04-2015, 1:00 AM","21-04-2015, 1:05 AM","21-04-2015, 1:10 AM","21-04-2015, 1:15 AM","21-04-2015, 1:20 AM","21-04-2015, 1:25 AM","21-04-2015, 1:30 AM","21-04-2015, 1:35 AM","21-04-2015, 1:40 AM","21-04-2015, 1:45 AM","21-04-2015, 1:50 AM","21-04-2015, 1:55 AM","21-04-2015, 2:00 AM","21-04-2015, 2:05 AM","21-04-2015, 2:10 AM","21-04-2015, 2:15 AM","21-04-2015, 2:20 AM","21-04-2015, 2:25 AM","21-04-2015, 2:30 AM","21-04-2015, 2:35 AM","21-04-2015, 2:40 AM","21-04-2015, 2:45 AM","21-04-2015, 2:50 AM","21-04-2015, 2:55 AM","21-04-2015, 3:00 AM","21-04-2015, 3:05 AM","21-04-2015, 3:10 AM","21-04-2015, 3:15 AM","21-04-2015, 3:20 AM","21-04-2015, 3:25 AM","21-04-2015, 3:30 AM","21-04-2015, 3:35 AM","21-04-2015, 3:40 AM","21-04-2015, 3:45 AM","21-04-2015, 3:50 AM","21-04-2015, 3:55 AM","21-04-2015, 4:00 AM","21-04-2015, 4:05 AM","21-04-2015, 4:10 AM","21-04-2015, 4:15 AM","21-04-2015, 4:20 AM","21-04-2015, 4:25 AM","21-04-2015, 4:30 AM","21-04-2015, 4:35 AM","21-04-2015, 4:40 AM","21-04-2015, 4:45 AM","21-04-2015, 4:50 AM","21-04-2015, 4:55 AM","21-04-2015, 5:00 AM","21-04-2015, 5:05 AM","21-04-2015, 5:10 AM","21-04-2015, 5:15 AM","21-04-2015, 5:20 AM","21-04-2015, 5:25 AM","21-04-2015, 5:30 AM","21-04-2015, 5:35 AM","21-04-2015, 5:40 AM","21-04-2015, 5:45 AM","21-04-2015, 5:50 AM","21-04-2015, 5:55 AM","21-04-2015, 6:00 AM","21-04-2015, 6:05 AM","21-04-2015, 6:10 AM","21-04-2015, 6:15 AM","21-04-2015, 6:20 AM","21-04-2015, 6:25 AM","21-04-2015, 6:30 AM","21-04-2015, 6:35 AM","21-04-2015, 6:40 AM","21-04-2015, 6:45 AM","21-04-2015, 6:50 AM","21-04-2015, 6:55 AM","21-04-2015, 7:00 AM","21-04-2015, 7:05 AM","21-04-2015, 7:10 AM","21-04-2015, 7:15 AM","21-04-2015, 7:20 AM","21-04-2015, 7:25 AM","21-04-2015, 7:30 AM","21-04-2015, 7:35 AM","21-04-2015, 7:40 AM","21-04-2015, 7:45 AM","21-04-2015, 7:50 AM","21-04-2015, 7:55 AM","21-04-2015, 8:00 AM","21-04-2015, 8:05 AM","21-04-2015, 8:10 AM","21-04-2015, 8:15 AM","21-04-2015, 8:20 AM","21-04-2015, 8:25 AM","21-04-2015, 8:30 AM","21-04-2015, 8:35 AM","21-04-2015, 8:40 AM","21-04-2015, 8:45 AM","21-04-2015, 8:50 AM","21-04-2015, 8:55 AM","21-04-2015, 9:00 AM","21-04-2015, 9:05 AM","21-04-2015, 9:10 AM","21-04-2015, 9:15 AM","21-04-2015, 9:20 AM","21-04-2015, 9:25 AM","21-04-2015, 9:30 AM","21-04-2015, 9:35 AM","21-04-2015, 9:40 AM","21-04-2015, 9:45 AM","21-04-2015, 9:50 AM","21-04-2015, 9:55 AM","21-04-2015, 10:00 AM","21-04-2015, 10:05 AM","21-04-2015, 10:10 AM","21-04-2015, 10:15 AM","21-04-2015, 10:20 AM","21-04-2015, 10:25 AM","21-04-2015, 10:30 AM","21-04-2015, 10:35 AM","21-04-2015, 10:40 AM","21-04-2015, 10:45 AM","21-04-2015, 10:50 AM","21-04-2015, 10:55 AM","21-04-2015, 11:00 AM","21-04-2015, 11:05 AM","21-04-2015, 11:10 AM","21-04-2015, 11:15 AM","21-04-2015, 11:20 AM","21-04-2015, 11:25 AM","21-04-2015, 11:30 AM","21-04-2015, 11:35 AM","21-04-2015, 11:40 AM","21-04-2015, 11:45 AM","21-04-2015, 11:50 AM","21-04-2015, 11:55 AM","21-04-2015, 12:00 PM","21-04-2015, 12:05 PM","21-04-2015, 12:10 PM","21-04-2015, 12:15 PM","21-04-2015, 12:20 PM","21-04-2015, 12:25 PM","21-04-2015, 12:30 PM","21-04-2015, 12:35 PM","21-04-2015, 12:40 PM","21-04-2015, 12:45 PM","21-04-2015, 12:50 PM","21-04-2015, 12:55 PM","21-04-2015, 1:00 PM","21-04-2015, 1:05 PM","21-04-2015, 1:10 PM","21-04-2015, 1:15 PM","21-04-2015, 1:20 PM","21-04-2015, 1:25 PM","21-04-2015, 1:30 PM","21-04-2015, 1:35 PM","21-04-2015, 1:40 PM","21-04-2015, 1:45 PM","21-04-2015, 1:50 PM","21-04-2015, 1:55 PM","21-04-2015, 2:00 PM","21-04-2015, 2:05 PM","21-04-2015, 2:10 PM","21-04-2015, 2:15 PM","21-04-2015, 2:20 PM","21-04-2015, 2:25 PM","21-04-2015, 2:30 PM","21-04-2015, 2:35 PM","21-04-2015, 2:40 PM","21-04-2015, 2:45 PM","21-04-2015, 2:50 PM","21-04-2015, 2:55 PM"],
title: {
text: 'Time'
},
labels: {
rotation: -90,
},
showLastLabel: true,
endOnTick: true
},
series: [{
name: 'TEST',
data: [124.22,125.67,127.12,122.77,122.77,121.33,121.33,119.89,122.77,122.77,124.22,121.33,122.77,124.22,121.33,119.89,119.89,119.89,122.77,119.89,118.46,118.46,119.89,119.89,122.77,121.33,121.33,121.33,122.77,121.33,122.77,121.33,121.33,124.22,119.89,119.89,121.33,121.33,122.77,119.89,118.46,118.46,119.89,117.03,118.46,117.03,119.89,117.03,117.03,118.46,118.46,121.33,121.33,122.77,122.77,121.33,125.67,124.22,127.12,125.67,124.22,128.58,125.67,127.12,122.77,127.12,121.33,121.33,115.6,111.35,112.76,105.74,107.14,107.14,104.35,100.2,98.83,101.58,100.2,97.45,97.45,96.09,94.72,93.36,93.36,94.72,96.09,93.36,93.36,92.01,93.36,92.01,92.01,92.01,94.72,92.01,89.31,89.31,90.66,92.01,87.97,87.97,89.31,87.97,90.66,89.31,89.31,90.66,89.31,90.66,92.01,90.66,86.63,87.97,89.31,89.31,86.63,89.31,87.97,87.97,86.63,86.63,87.97,85.29,87.97,87.97,87.97,87.97,86.63,87.97,86.63,87.97,85.29,86.63,86.63,85.29,86.63,85.29,86.63,87.97,86.63,86.63,85.29,85.29,85.29,83.96,85.29,85.29,83.96,83.96,83.96,83.96,83.96,83.96,83.96,83.96,83.96,83.96,83.96,82.63,83.96,82.63,81.31,82.63,83.96,82.63,82.63,82.63,79.98,81.31,81.31,82.63,82.63,81.31,81.31,81.31,81.31,81.31,82.63,81.31,81.31,79.98,79.98,79.98,81.31,79.98,79.98,79.98,79.98,79.98,79.98,79.98,79.98,79.98,78.67,79.98,79.98,78.67,78.67,79.98,78.67,82.63,79.98,78.67,79.98,78.67,78.67,77.35,78.67,77.35,78.67,78.67,78.67,79.98,83.96,90.66,92.01,94.72,97.45,100.2,102.96,105.74,101.58,98.83,96.09,94.72,93.36,92.01,89.31,90.66,89.31,86.63,85.29,86.63,85.29,85.29,85.29,82.63,83.96,82.63,82.63]
}]
});
});
The chart in this URL shows the last xaxis value as 243 instead of "21-04-2015, 2:55 PM" value, which is the last in the series.
Have tried with :
showLastLabel: true,
endOnTick: true
but no luck.
Thanks in advance, Naveen.

This is happening because you have too many labels you're trying to display on the axis. It is only showing every third label right now, and the way it ends, the last two categories are not in the loop.
There are two things you can do.
1) reduce your font size for the labels, and take a look at the step and tickInterval properties.
Example:
http://jsfiddle.net/jlbriggs/58jy1zhd/4/
But really, that's just kind of silly. That's way too many labels to make sense of, and it uses a full half of the visual real estate to display them, and has to display them sideways, making it even harder to make sense of.
So I recommend 2) use a date time axis. You have all of the date information. You can either pass those dates as the x values of your data, or, if they're always going to be uniform (ie the same distance apart), as they appear to be already, you can use the pointStart and pointInterval properties.
Example:
http://jsfiddle.net/jlbriggs/58jy1zhd/3/
It doesn't show every label. But it's pretty futile, and ultimately useless to try showing every label of a time series.
You can manipulate the axis to make sure it shows the first and last, and you can format the label output to include the date portion, or any other thing that you want it to.
[[edit to add label formatting reference links:
http://api.highcharts.com/highcharts#xAxis.labels.formatter
http://api.highcharts.com/highcharts#xAxis.labels.format
http://api.highcharts.com/highcharts#xAxis.dateTimeLabelFormats
Example using the formatter function to display date and time for each tick, with a tick every 4 hours:
http://jsfiddle.net/58jy1zhd/7/

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

where query in daterange in rails with postgresql

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

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"]

Resources