Difference between dates from Database in another location and client's local time - date

I have a requirement to disregard records from the DB that are more than 10 minutes old. However, the DB server is present in a different time zone than the app server. I tried to leverage the time zone details from the timestamp column value but it seems that they do not store the time zone details in that column value (bad design?). However, i have found a way to get this information for the DB instance using a query:
select dbtimezone from dual.
However, most of the implementations in java support time zones via names and not offset information. I need to be able to translate this offset exactly to a timezone (EST etc) so that i may not miss any DST related time in my calculations. like so:
TimeZone dbZone = TimeZone.getTimeZone(10000); // offset is +10000
Calendar cal = Calendar.getInstance(dbZone);
cal.setTime(new Date());
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(dbZone);
Date parsedDate = df.parse(df.format(cal.getTime()));
The plan is to convert the present client/app time to the DB specific timezone time and perform the difference between the two.
This cannot be done in a query due to some restraints. Please do not ask me to write a query to get latest records etc. Must be done in Java.
Any tips?

I am guessing it might get you in the right direction. You can try the following so you know the offset from EST and can do the calculation accordingly:
SELECT TZ_OFFSET('US/Eastern') FROM DUAL;
So a return of -3:00 would mean it is PST time. Maybe you've already tried this?

Related

Powerapps Filter Collection By Today's Date

Good day all,
I am trying to filter todays result in SQL table to a collection in powerapps. The column "dt" represents the column in sql of datetime type.
This is my powerapps filter:
ClearCollect(myCollectionName, Filter(myDatasource, Text(dt,"dd/mm/yyyy") = Text(Now(),"dd/mm/yyyy" )));
Seems like the collection is still empty even there is data for today in sql. May I know if my approach is the correct way in filtering?
Short answer: the data is likely being changed based on the client time zone. To fix it, you can update it by applying the time zone offset to the data from the SQL table, something along the lines of:
ClearCollect(
myCollectionName,
Filter(
myDatasource,
Text(DateAdd(dt, TimeZoneOffset(dt), Minutes), "dd/mm/yyyy") =
Text(Now(), "dd/mm/yyyy")))
Long(er) answer: the datetime type in SQL Server represents an absolute value of date and time. For example, the value '2021-12-23 09:30:00' represents 9:30 in the morning of the 23rd day of December, 2021 - at any part of the world. The date/time type in Power Apps, however, represents a point in time, typically referring to the local time where the app is being executed (or created). For example, if I selected that value and I'm in the US Pacific Time Zone (UTC-08:00), that would represent the same value as if someone in London (UTC+00:00) selected 2021-12-23 17:30:00. Since the two types represent different concepts, we may have mismatches like you are facing. To fix this, we can either use a type in SQL Server that has the same semantics as Power Apps (for example, 'datetimeoffset'), or adjust the time when it is being transferred between SQL and Power Apps.
The blog post at https://powerapps.microsoft.com/en-us/blog/working-with-datetime-values-in-sql explains in more details how to work with date/time values in SQL and Power Apps.

How to deal with dates in global system

Let's say that I need to create 'chat-like' system. Of course I need to deal with dates somehow.
I read about it a lot and I have some knowledge but I really don't know how to use it.
I would like to store message date in UTC (postgres 12)
Each user should be able to select his time zone and this time zone should be saved into database (standard approach)
When message is retrieved from database I need to convert message date into valid local date based on user selected timezone.
This is really all I need to do and here problem starts:
In postgres date is stored with offset f.e 2020-05-01 00:00:00+02, but I want to store timezone in another table, not here
How can I store user timezone? I should use names like "EST5EDT" or use time offsets as integer?
Where can I find list of all timezones to present user? (Each global website f.e. facebook has list of timezones with offsets, where can I find list of all valid timezones?)
How can I select date with user appropriate timezone? f.e.
SELECT convert_to_user_date("Date", "timezonename??")
FROM "Messages"
Is this correct way to achieve my goal?
These days you don't have to resort to UTC. You can store full timestamps with time zone. This way e.g. you won't lose DST status at the moment the timestamp was recorded in the database.
https://www.postgresql.org/docs/current/datatype-datetime.html
You can easily select the timestamp stored with any time zone shifted to target user's time zone (assuming it's stored somewhere in user preferences). The syntax is SELECT ... AT TIME ZONE
https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-ZONECONVERT
You are very close to a workable setup.
First, use timestamp or timestamp without timezone column data type to store those UTC date/time stamps.
Second, store your users' preferred time zones in varchar(63) columns in the form Asia/Kolkata or America/Halifax.
Third, use postgresql's built in view pg_timezone_names to get a list of valid time zones. You can use it to populate a pulldown list of choices in your user-settings screen.
If you have time for some real excellence in your user-settings screen, you can suggest time zone settings you guess from the users' ip adresses and allow them to change them if your guess was wrong. Read this. How to get Time Zone through IP Address in PHP
Then, when your application starts using postgresql on behalf of any user, look up that user's chosen time zone in your users table, and use it in this SQL command. SET TIME ZONE 'America/Halifax'; (whatever the user's choice is).
Then when you retrieve your time stamps, they will be rendered in the user's local time, and when you store the they'll be in UTC.
The 'toobz are full of advice about this. Here's something that might be useful. How to get Time Zone through IP Address in PHP
Use the data type timestamp with time zone. Don't be worried by the name — that data type really represents an absolute point of time and does not store time zone information.
The only thing you have to do is to set the timezone parameter correctly for the time zone of the client connection, then the value will be represented correctly in that time zone. PostgreSQL does all the work for you.
If you don't like the string representation (e.g., you are disturbed by the time zone offset displayed), use to_char to format the output the way you like:
CREATE TABLE dates (x timestamp with time zone NOT NULL);
SET timezone = 'Europe/Vienna';
INSERT INTO dates VALUES ('2020-06-01 03:00:00');
SET timezone = 'Asia/Kolkata';
SELECT to_char(x, 'YYYY-MM-DD HH24:MI:SS') FROM dates;
to_char
---------------------
2020-06-01 06:30:00
(1 row)

PostgreSQL - extracting date ranges in local time?

CURRENT SITUATION:
I have a table of wildfire incidents with a timestamp with time zone (timestamptz) field to track when the observation occurred.
Everything in the data creation process is in UTC: the incoming data from the source, the app server that inserts the data, the insert python code (appends a "Z" to the time), and the database server are all in UTC.
The incidents' geographic extent spans several time zones in the US, Canada, and Mexico.
PROBLEM:
I've been querying on a day's worth of data in UTC time, but need to extract out data relative to local time. The midnight to midnight range will be different in each time zone.
My use case now is one day, but I was asked to consider arbitrary time ranges. E.g.: find all incidents in the hottest part of the day (say 10:00 to 18:00) local time.
This table is quite large and I have an index on the timestamptz field right now. Any changes I make will need to work with an index.
Account for daylight saving time.
I have a method to get the time zone for each record, so I don't need help with that.
I created a test table for this with a timestamptz field ts_with and a varchar field for the time zone tz. The following query returns what I want, so I feel like I'm making progress.
SELECT
name, test_tz.ts_with, test_tz.tz,
TIMEZONE(test_tz.tz, test_tz.ts_with) as timezone_with
FROM fire_info.test_tz
WHERE TIMEZONE(test_tz.tz, test_tz.ts_with) BETWEEN
'2018-08-07 00:00:00' AND '2018-08-07 23:59:59';
QUESTIONS:
Will this use my index? I'm thinking the timezone function will avoid it. Any solution for that? I'm considering adding another condition to the where clause that selects on timestamptz buffered by a day on either side. That would use the index and then the timezone function isn't sorting through too much data (~6k records per day during fire season). Would PG figure that out?
The timezone function is giving me DST offsets (e.g.: Denver is currently UTC-06). I assume I'll get standard time after DST ends. If I run a query in December for data in August, will it apply standard time or DST?
thanks!!!
The way you wrote the query, it cannot use an index on ts_with.
To use an index, the condition would have to be of the form ts_with <operator> <constant>, and there is no way to rewrite the query in that fashion.
So you should create a second index on timezone(test_tz.tz, test_tz.ts_with).

Perl DBIx::Class: getting the current time from the Database

Here is my problem:
I want to calculate how long ago a record was updated in a DB.
The DB is in PostgreSQL, the update_time field is populated by a trigger that uses CURRENT_TIMESTAMP(2). The field is inflated to a DateTime object by DBIx::Class. I get the current time in my code using DateTime->now()
My problem is that when I retrieve the field value, it's off by 1 h (ie it's 1h ahead of DateTime->now()). I am in the CET time zone, so 1h ahead of UTC currently.
The right way to solve the problem is likely at the DB level. I have tried to replace CURRENT_TIMESTAMP with LOCALTIMESTAMP, to no avail.
I think actually a more robust solution (ie one that doesn't rely on getting the DB right) would be to get the current time stamp from the DB itself. I really just need the epoch, since that's what I use to compute the difference.
So the question is: is there a simple way to do this: get the current time from the DB using DBIx::Class?
A different way to get the DB and DateTime to agree on what the current time is would also be OK!
You can use dbh_do from your DBIx::Class::Storage to run arbitrary queries. With that, just SELECT the CURRENT_TIMESTAMP.
my ( $timestamp ) = $schema->storage->dbh_do(
sub {
my ($storage, $dbh) = #_;
$dbh->selectrow_array("SELECT CURRENT_TIMESTAMP");
},
);
I always recommend to do all date/time related things on the app server and not rely on the database server(s). Essentially that means to not use a trigger but pass the datetime on insert/update and make it mandatory (NOT NULL).
Besides that you should store datetimes in UTC and convert to your local or other required timezone in your code.
Your issue likely happens because of an incorrect or missing timezone configuartion in which case DateTime defaults to its floating timezone.

MongoDB: how to generate local date?

I generate a date in MongoDB shell:
var d = new Date();
d
but the date result doesn't match the time in my location
However, the same code in javascript, the console.log(d) can output the correct time in my location
Why? How can I generate my local time in MongoDB?
This will give you the timezone (which you should store separately inside your application).
var myDate = new Date();
document.write(myDate.getTimezoneOffset());
MongoDB (including the console) will by default always generate and stores in UTC, however ISODates do support a timezone offset ( http://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC ) however you would need to manage the creation of that offset from your application.
As #CRUSADER mentions it is normally better to store the users offset within the row or even not at all, particularly if your user could be accessing from many locations with many different timezones. In this case it might actually be better to modify the dates within your client JavaScript to take care of the difference in timezone from where they are currently accessing the page.