Time zone for Force.com API fiscal date literals? - api

I have a question about fiscal date literals in the Force.com API (http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_soql_select_dateformats.htm):
For which time zone are date ranges calculated?
For example, suppose we execute the query:
SELECT Id FROM Opportunity WHERE CloseDate = THIS_FISCAL_QUARTER
where, according to our company's fiscal settings, THIS_FISCAL_QUARTER runs from Jan 1 to Mar 31.
Does the range for THIS_FISCAL_QUARTER use...
the user's time zone? For example, if the user's time zone is GMT-8, THIS_FISCAL_QUARTER = Jan 1 00:00 GMT-8 to Mar 31 23:59 GMT-8 (or Jan 1 08:00 UTC to Mar 31 07:59 UTC)
the company's default time zone (according to the company profile)? For example, if the company's default time zone is GMT-8, THIS_FISCAL_QUARTER = Jan 1 00:00 GMT-8 to Mar 31 23:59 GMT-8 (or Jan 1 08:00 UTC to Mar 31 07:59 UTC)
UTC? THIS_FISCAL_QUARTER = Jan 1 00:00 UTC to Mar 31 23:59 UTC
something else?

From my experience (fun with reports, not queries) the note from all the way on bottom is valid also for time literals. So it uses running user's timezone setting.
These values are offset by your timezone. For example, in the Pacific timezone, the earliest valid date is 1699-12-31T16:00:00, or 4:00 PM on December 31, 1699.
Maybe you can simply create a test record with datetime field just slightly outside the fiscal quarter and query for it "WHERE mydatetimefield__c > THIS_FISCAL_QUARTER"?
See also http://forums.sforce.com/t5/General-Development/SOQL-Date-literal-TODAY-is-evaluated-incorrectly/m-p/43607

Related

postgresl SQL statement displays dates outside the interval

On RHEL, the date/time at the command prompt is in UTC time.
I query my table for dates in the last hour, but it returns me other dates/times. I don't know if it is timezone related but I am super confused how to work with it
select to_char(update_dt, 'DD Mon YYYY HH12:MI'),data
from mytable
where update_dt > current_date - interval '1' hour
to_char | data
-------------------+----------------
07 May 2020 12:37 | blah
07 May 2020 12:37 | blah
07 May 2020 12:37 | blah
07 May 2020 12:37 | blah
07 May 2020 12:37 | blah
07 May 2020 05:23 | huh
07 May 2020 05:23 | huh
07 May 2020 05:22 | huh
[root#ip-172-31-1-28 ~]# date
Thu May 7 13:25:03 UTC 2020
This expression:
where update_dt > current_date - interval '1' hour
goes since midnight yesterday, because current_date is only the date at midnight (at the beginning of the date).
You seem to want the time included:
where update_dt > now() - interval '1' hour
You can also use:
where update_dt > current_timestamp - interval '1' hour
but now() is easier to type.

SQL Create a midweek week-ending date without using a joining lookup table

I'm wondering if it is possible to build a ORACLE SQL FUNCTION to return a mid-week date rather than using a joining table.
The week ends on a Wednesday so if we had date of Friday 5th Jan then the week ending date would be the following Wednesday 10/01/2018
MON 1ST JAN - 03/01/18
TUES 2ND JAN - 03/01/18
WED 3RD JAN - 03/01/18
THURS 4TH JAN - 10/01/18
FRI 5TH JAN - 10/01/18
SAT 6TH JAN - 10/01/18
SUN 7TH JAN - 10/01/18
MON 8TH JAN - 10/01/18
TUES 9TH JAN - 10/01/18
WED 10TH JAN - 10/01/18
THURS 11TH JAN - 17/01/18
The reason I'm investigating the function route is to future proof the process so I do not have maintain a second lookup table & get rid of unnecessary joins.
I've managed to google a work around
SELECT NEXT_DAY('25-JAN-2018 00.00', 'WEDNESDAY')FROM DUAL;
You may need something like the following:
select d,
case
when trunc(d, 'IW') +2 >= d
then trunc(d, 'IW') +2
else trunc(d, 'IW') +9
end as next_wed
from (
select date '2018-01-01' + level -1 as d
from dual
connect by level <= 11
)
This gets the monday of the week in which your date is contained and then adds 2 or 9 depending on the fact that adding 2 gives a day before the inut date or not.
Another way could be by checking if the input date is a before or after the wednesday in its week:
case when to_char(d, 'D') <= 3
then trunc(d, 'IW') +2
else trunc(d, 'IW') +9
end as next_wed

Compare NSDates across timezones

I'd like to compare and filter NSDates to determine whether there are any for today regarding the users current timezone.
Let's say I've a user located in Los Angeles (UTC-8 hours) and the following dates:
TargetDate
UTC: 2 pm (14:00) - 12. Feb 2017
LocalTime: 10 pm (22:00) - 12. Feb 2017
Now
UTC: 10 pm (22:00) - 11. Feb 2017 // Change of date!
LocalTime: 6 pm (06:00) - 12. Feb 2017
Today
UTC: 00 am (00:00) - 11. Feb 2017 // Begin of today
Tomorrow
UTC: 00 am (00:00) - 12. Feb 2017
In the next step I'd like to compare the TargetDate, Today and Tomorrow to determine, if the TargetDate is between Today and Tomorrow. This is where the problem is. When I compare the dates I receive an answer that it is of course not between these dates.
+ (BOOL)date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate
{
if ([date compare:beginDate] == NSOrderedAscending)
return NO;
if ([date compare:endDate] == NSOrderedDescending)
return NO;
return YES;
}
What I can do, is to convert the UTC date, TargetDate, to the local timezone but I'm very confused whether this is the best solution. In this post it's mentioned that you shouldn't do this because it confuses the whole problem.
Does anyone has an idea, how to solve this problem?
The problem you are having is actually here:
Today
UTC: 00 am (00:00) - 11. Feb 2017 // Begin of today
Tomorrow
UTC: 00 am (00:00) - 12. Feb 2017
You're deciding that the "day" is the UTC day. Instead, you need to determine the day in the target time zone.
Today
LocalTime: 00 am (00:00) - 11. Feb 2017 // Begin of today
UTC: 08 am (08:00) - 11. Feb 2017 // Equivalent UTC
Tomorrow
LocalTime: 00 am (00:00) - 12. Feb 2017 // Begin of tomorrow
UTC: 08 am (08:00) - 12. Feb 2017 // Equivalent UTC
Do keep in mind a few other things:
Compare with half-open intervals: StartOfToday <= SomePointToday < StartOfTomorrow (inclusive start, exclusive end).
America/Los_Angeles is not always UTC-8. It switches to UTC-7 during daylight saving time.
Not every day starts at midnight. For example, America/Sao_Paulo on 2016-10-16 started at 01:00. The 00:00 hour was skipped for DST.
If you just care about some point on that day, rather than the entire day, compare at 12:00 noon, rather than at 00:00 midnight. It avoids the DST problem.

Add nchar field to DateTime in Informix

I have a datetime field that stores times in UTC format. There's another nchar field that stores the time zone difference based on a location. I'm trying to combine the two for a report so that the time displayed matches the appropriate time zone.
time_stamp | time_zone
---------------------------------
2015-11-24 21:00:00 | -0500
2015-11-23 15:00:00 | -0600
Expected output:
2015-11-24 16:00:00
2015-11-23 09:00:00
I was able to get this to work by using:
extend(time_stamp, year to minute) + (CAST(LEFT(time_zone,3) as int)) units hour
While this technically works for the current situation, I really don't like using the CAST and LEFT functions on the time_zone field since it breaks if the value is not negative. Seems like there's a much better solution, possible something with TO_CHAR. In an informix database, what is the proper way to combine the dateime and nchar fields so that the output time is correct? Ideally I would like to output in non 24 hr format (4:00 PM, etc...) but at this point I'm mainly focused on getting the correct time.
Ideally, your time zone column would be an INTERVAL HOUR TO MINUTE type; you'd then simply add the two columns to get the desired result. Since it is a character type, substringing in some form will be necessary. Using LEFT is one option; SUBSTRING is another; using the Informix subscripting notation is another. The CAST isn't crucial; Informix is pretty good about coercing things.
Unless you actually want only hours and minutes in the result (which is a legitimate choice), your EXTEND operation is unnecessary and undesirable; it means your result won't include the seconds value from your data.
Note that some time zones include minutes values. Newfoundland is on UTC-04:30; India is on UTC+05:30; Nepal is on UTC+05:45. (See World Time Zone for more information.) Getting the minutes accurate is harder because the sign has to be carried through.
As to formatting in AM/PM notation, apart from the question 'why', the answer is to use the TO_CHAR() function and a ghastligram expressing the time format that you want.
TO_CHAR()
GL_DATETIME
GL_DATE
Demonstration:
create table zone_char(time_stamp datetime year to second, time_zone nchar(5));
insert into zone_char values('2015-11-24 21:00:00', '-0500');
insert into zone_char values('2015-11-23 15:00:00', '-0600');
insert into zone_char values('2015-11-22 17:19:21', '+0515');
insert into zone_char values('2015-11-21 02:56:31', '-0430');
Various ways to select the data:
select extend(time_stamp, year to minute) + LEFT(time_zone,3) units hour,
time_stamp + LEFT(time_zone,3) units hour,
time_stamp + time_zone[1,3] units hour,
time_stamp + time_zone[1,3] units hour + (time_zone[1] || time_zone[4,5]) units minute,
TO_CHAR(time_stamp + time_zone[1,3] units hour + (time_zone[1] || time_zone[4,5]) units minute,
'%A %e %B %Y %I.%M.%S %p')
from zone_char;
Sample output:
2015-11-24 16:00 2015-11-24 16:00:00 2015-11-24 16:00:00 2015-11-24 16:00:00 Tuesday 24 November 2015 04.00.00 PM
2015-11-23 09:00 2015-11-23 09:00:00 2015-11-23 09:00:00 2015-11-23 09:00:00 Monday 23 November 2015 09.00.00 AM
2015-11-22 22:19 2015-11-22 22:19:21 2015-11-22 22:19:21 2015-11-22 22:34:21 Sunday 22 November 2015 10.34.21 PM
2015-11-20 22:56 2015-11-20 22:56:31 2015-11-20 22:56:31 2015-11-20 22:26:31 Friday 20 November 2015 10.26.31 PM
And note how much easier it is when the time zone is represented as an INTERVAL HOUR TO MINUTE:
alter table zone_char add hhmm interval hour to minute;
update zone_char set hhmm = time_zone[1,3] || ':' || time_zone[4,5];
SELECT:
select time_stamp, hhmm, extend(time_stamp + hhmm, year to minute),
time_stamp + hhmm,
TO_CHAR(time_stamp + hhmm, '%A %e %B %Y %I.%M.%S %p')
from zone_char;
Result:
2015-11-24 21:00:00 -5:00 2015-11-24 16:00 2015-11-24 16:00:00 Tuesday 24 November 2015 04.00.00 PM
2015-11-23 15:00:00 -6:00 2015-11-23 09:00 2015-11-23 09:00:00 Monday 23 November 2015 09.00.00 AM
2015-11-22 17:19:21 5:15 2015-11-22 22:34 2015-11-22 22:34:21 Sunday 22 November 2015 10.34.21 PM
2015-11-21 02:56:31 -4:30 2015-11-20 22:26 2015-11-20 22:26:31 Friday 20 November 2015 10.26.31 PM

Modifying date to enable search in mysql DateTime format

I have an UI, in which we which we select a date range, and then perform a query to check orders within that range.
So the valid formats accepted are
a) 2013-04-01 17:00:00 - 2013-04-16 18:00:00
b) 2013-04-01 17:00:00 - 2013-04-16
c) 2013-04-01 - 2013-04-16
I split it in ruby to give me start_date and end_date. I don't have to touch the start time, as it ready for the sql query.
But the end_date has to be modified because to perform a ranged query created_at BETWEEN '2013-04-01 17:00:00' AND '2013-04-16' does not give me the results of 16th which should be included in the result set. (As it compares to 2013-04-16 00:00:00)
So this is the working solution, I came up with
end_date = Time.parse(end_date).strftime("%T")=="00:00:00" ? (end_date.to_s) + " 23:59:59" : end_date.to_s
Is there a better way to do this as the above looks quite confusing? (Looking or 1-2 line answers, not more)
You could use the DateTime.parse(str) method:
date_str = "2013-04-16"
date = DateTime.parse(date_str)
#=> Tue, 16 Apr 2013 00:00:00 +0000
date_time_str = "2013-04-16 18:00:00"
date = DateTime.parse(date_time_str)
#=> Tue, 16 Apr 2013 18:00:00 +0000
And then you could test the .hour (or .minute) and set the end_date to end_of_day if no time was selected:
end_date = (date.hour == 0 && date.minute == 0) ? date.end_of_day : date
Little improvement: You could test if the parsed date is equal to the beginning of this date (no hours/minutes/seconds):
date = DateTime.parse("2013-12-12")
#=> Thu, 12 Dec 2013 00:00:00 +0000
date.beginning_of_day
#=> Thu, 12 Dec 2013 00:00:00 +0000
end_date = (date.beginning_of_day == date) ? date.end_of_day : date
#=> Thu, 12 Dec 2013 23:59:59 +0000
To solve the problem when user enters a DateTime like 2013-04-16 00:00:00, you can use .include? to check if the string contains the '00:00:00' part:
date_str = "2013-04-16 00:00:00"
date = DateTime.parse(date_str)
end_date = date if date_str.include?('00:00:00') # means the user explicitly wants the time at 00:00 and 00 second
end_date ||= (date.beginning_of_day == date) ? date.end_of_day : date # set end_date if end_date.nil?