Remove timezone completely from SQL Server - node.js

EDIT: Some users noted that this is a duplicate of ADO.NET question at
How can I get DateTime data from SQL Server ignoring time zone issues?
Please DO READ my tags, and my codes. This is nodejs question,
that has nothing to do with ADO library whatsoever. It doesn't
even run on Windows. The option noted at the link provided doesn't even exists at mssql-npm
I am creating a database for company attendance, which spans for 3 timezones.
The problem with SQL Server is that I read the working hour differently from each timezone. It registered like 1969-12-31T23:00:00.000Z, and registers as 06:00 for one timeline, and 08:00 for another. I need it to be exactly at 08:00 regardless of timezone. It means, 08:00 at western part of my country, and also 08:00 at eastern part of my country.
When I try to disable UseUTC, nodejs translated my timezone twice. For example, this is when I sent masuk field as 08:00
Sent to server:
Query sent to SQL Server:
UPDATE shift SET name = 'Shift 1', masuk = '2019-10-28T01:00:00.000Z', keluar = '2019-10-28T10:00:00.000Z', tolerance = 15 WHERE id = 1
Received the result back
And shown to the user as:
My country sits at GMT+7 to GMT+9. I don't mind if I have to flatten the timezone. But how to do that? Is there a way to read the time completely ignoring the time zone? It makes my work unnecesarily complicated.
I am using:
SQL Server 2012
Material UI
date-fns
Nodejs 12
mssql module
and this is my code to get the time from user input
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardTimePicker
key={component.field.toString()}
variant="inline"
value={value}
label={component.title}
onChange={this.eventHandler(component.field).bind(this)}
format="HH:mm"
/>
</MuiPickersUtilsProvider>
Thank you for help.
THe database uses time(7) to store the time

Related

How to remove gmt from postgreSQL db across date columns?

I am using PostgreSQL in my application. Simply I have declared a particular model attribute as sale_date and have set its data type to Date as follows:
//definition in backend model
sale_date: {
type: Sequelize.DATE,
allowNull: true,
}
And I am using moment on the frontend which is on react. I am giving the user a calendar option to select a date and setting the time as 00:00:00 so that the DB does not pick the local time. However, one issue I am facing is that it automatically adds +05 to the time which is the timezone I am currently in.
2021-06-01 05:00:00+05
Here because of +05, the time became 05:00:00 automatically, how to avoid this, I need time to stay 12am always so that the calendar date does not change even if I upload a document at 11:00 pm.
Using moment like this on the frontend
//From front-end implementation
sale_date = moment
.utc(object.sale_date)
.format("YYYY-MM-DD 00:00:00Z");
How do I achieve the desired behavior?
I think that .utcOffset() can be helpful for your case.
const date = moment().format();
const date2 = moment
.utc(date)
.utcOffset(0)
.format();
console.log(date);
console.log(date2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
Documentation of utf offset

postgresql to_char(date, 'day') get different result when using nodejs

UPDATE 2
Using the suggestions from #Bergi, I added a db execution helper to set the timezone before executing the query. This allows me to control the timezone based on the logged in user's preferences.
async function execWithTZ(sql, params, timezone) {
const client = await this.pool.connect();
await client.query<any>(`SET TIMEZONE TO '${timezone}'`, []);
return client.query<any>(sql, params);
}
const result = await execWithTZ('SELECT ...', [], 'Australia/Sydney');
QUESTION
I am trying to get Postgresql to return the day of the week of a specific date in a view. I later use this to display values by day.
The data is in a table with a column named updated which is a timestamptz field.
When running the following query using DBeaver SQL client against a PostgreSQL 12 database I get the values as I expect, with records updated on Thursday local time (just after midnight) showing up as Thursday
SELECT
count(v.id) AS count,
btrim(to_char(v.updated, 'DAY'::text)) AS day,
date_trunc('DAY'::text, v.updated) AS "updatedDay"
FROM table v
GROUP BY (to_char(v.updated, 'DAY'::text)), (date_trunc('DAY'::text, v.updated))
I put this in a view and when I query this view using node-postgres the counts are for the previous day (Wednesday), which I presume is because the database thinks it should interpret the dates in the UTC timezone.
To further prove the point, when I change the above query to use DAYTZ instead of just DAY in DBeaver I get THURSDAYAEST but in nodejs as result I get WEDNESDAYUTC
Changing all my dates to be without timezone and forcing everything to UTC on the way in is not an option for me.
How can I make node-postgres tell the database what timezone I want these dates interpreted as so that I can get the correct day?
UPDATE 1
I managed to get PostgreSQL to return the correct values to postgres node by setting the database user's timezone.
ALTER ROLE visuo_ingest SET TIMEZONE TO 'Australia/Sydney';
Now the counts for things that happened on Thursday Sydney time is counted for Thursday and not Wednesday.
Still interested in a way to do this on the connection rather than the database user level.
Still interested in a way to do this on the connection rather than the database user level.
You already found the right setting, there's no reason to alter it on a role only. You can also change the setting in a client session by running the SET command
SET TIMEZONE TO 'Australia/Sydney';
Just put that in a pgClient.query("…"); right after connecting the client.

Mongoose datetime and timezone, how to get datetime based on server timezone

The first answer of this question suggests that mongoose would adapt the date according to server timezone when retrieving data.
However, I don't have this comportement.
I set the (node) server timezone with :
process.env.TZ='Europe/Paris'
For exemple if I create a simple model like :
const mongoose = require("mongoose");
const testSchema = new mongoose.Schema({
myDate: { type: Date, required: true },
}, { timestamps: true });
exports.Comment = mongoose.default.model('TestSchema', testSchema);
But if I create a date with 2020-01-01 20:20:20, when doing TestSchema.find() the date will be: 2020-01-01T19:20:20.000Z so there are two things that I don't understand :
Europe/Paris is actually UTC +2, so I would expect the date to be either 2020-01-01T18:20:20.000Z in UTC or 2020-01-01T20:20:20.000Z with the server timezone
How to have mongoose automatically set the date to the correct timezone?
I know that myDate is a Date object, so I can convert it manually but I'd rather not have to do it myself for simple reasons like forgetting to convert one of the dates in the application or not having to do it every time a Date field is added
An easy solution that I can think of would be to register a global plugin for mongoose which would use schema.set('toJSON', ... and schema.set('toObject', ...) with the transform method so I can loop through schema fields and if the field is a Date, update it to my timezone.
But I see two problems with this approch :
It doesn't sound very good performance-wise if I am querying a lot of documents each with a lot of fields
As you can see here I am currently not able to register global plugins...
What would be the best method to get the date in the server timezone format? I would rather still store them in UTC but set the hour according to the server timezone.
EDIT :
I just saw that while console.log(myDate) outputs 2018-01-01T19:20:20.000Z console.log(myDate.toString() outputs Mon Jan 01 2018 20:20:20 GMT+0100 (Central European Standard Time) so it seems likes this could be used, even tho I'd rather still have a Date object and converting it to string just before sending it to the client (would need some formatting tho since this format is not very user friendly). But then again, how would I do this globally and not for every date
A few things:
Europe/Paris at 2020-01-01T20:20:20 is UTC+1. It doesn't switch to UTC+2 until Summer Time kicks in on March 29th. Reference here. Thus the conversion to 2020-01-01T19:20:20Z is correct.
The output of console.log when passed a Date object is implementation specific. Some implementations will emit the output of .toString() (which is in local time in RFC 2822 format), and some will emit the output of .toISOString() (which is in UTC in ISO 8601 extended format). That is why you see the difference.
In general, it is not good to send a local time without also sending a time zone offset. ISO 8601 format is ideal, but you should send either 2020-01-01T19:20:20Z, or 2020-01-01T20:20:20+01:00. Don't just send the date and time without an offset to the client. Otherwise, if your client could be in a different time zone then they would interpret the value incorrectly.
Keep in mind that Date objects are not time zone aware. They contain only a Unix timestamp internally, and they convert only to the system's local time zone for the functions that work in local time. They cannot work in any other time zone.
Relying on the system local time zone is bad for portability. One doesn't always have the ability to change it, and it doesn't do well when you have to work in multiple time zones. It would be better to not rely on setting a local time zone from Node's TZ variable. Instead, consider writing your code to be independent of any local time zone setting.
A time zone aware date library can help with most of your concerns. I can recommend Luxon, js-Joda, Moment + Moment-Timezone, or date-fns + date-fns-timezone.
"how would I do this globally" is something I'm not following in your question. Try the approach I described, and if you still have issues then open a new question. Try to be specific and ask a single question. You're likely to get better results that way. Please read How do I ask a good question? and How to create a Minimal, Complete, and Verifiable example. Thanks.
To solve the issue:
npm i mongoose-timezone
In your schema file:
import timeZone from "mongoose-timezone";
const testSchema = new mongoose.Schema({
myDate: { type: Date, required: true },
}, { timestamps: true });
// mongoose will save the dates based on user's timezone
testSchema.plugin(timeZone)
mongoose-timezone basically adds the current timezone offset to the
date before store and removes the offset when retrieving data. This
way dates are kept proportional in the database and in the app.

How to get the local timezone from the system using nodejs

Is there a way to obtain the local timezone from the system (eg:- ubuntu) using nodejs?
I used moment.js to extract the date and time values. But couldn't find a way to extract the timezone as well.
The existing answers will tell you the current timezone offset, but you will have issues if you are comparing historic/future points in time as this will not cater for daylight saving changes.
In many timezones, the offset varies throughout the year and these changes occur at different dates or not at all depending on the latitude. If you only have UTC time and an offset, you can never be sure what the offset will be in that location at various other times during the year.
For example, a UTC+2:00 offset could refer to Barcelona in the summer or Ivory Coast all year round. The 2hr offset will always display the correct time in Ivory Coast but will be 1hr out for half the year in Barcelona.
Check out this great article covering the above.
How do we cater for all these time zone issues? Well, it's pretty simple:
Save all times in UTC
Store the time zone string for where this event occurred
In modern browsers or node.js, you can get the local IANA time zone string like this:
Intl.DateTimeFormat().resolvedOptions().timeZone // eg. 'America/Chicago'
You can then use this timezone string in a library like Luxon to help offset your captured UTC times.
DateTime.fromISO("2017-05-15T09:10:23", { zone: "Europe/Paris" });
It is very simple.
var x = new Date();
var offset= -x.getTimezoneOffset();
console.log((offset>=0?"+":"")+parseInt(offset/60)+":"+String(offset%60).padStart(2, "0"))
And there is nothing else or you can see if momentJS can help you or not.
Note: This answer is outdated, you can suggest to add in it.
It is this easy, no libraries needed:
console.log("test ...")
let d = new Date()
console.log("UTC time " + d)
let ank = d.toLocaleString('en-US', { timeZone: 'America/Anchorage' });
console.log("your time zone " + ank)
How to see the exact time zone names on most servers:
ls /usr/share/zoneinfo
Works flawlessly:
You'll get the correct time-text regardless of daylight savings issues, etc etc.
Handy related mysql tip:
On almost all servers, mysql also needs to know the tz info.
Basically the solution is, on the shell
sudo mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql
.. google more about it.
I solved this using moment.js (http://momentjs.com/docs/)
var moment = require('moment');
var offset = moment().utcOffset();
console.log(''.concat(offset < 0 ? "-" : "+",moment(''.concat(Math.abs(offset/60),Math.abs(offset%60) < 10 ? "0" : "",Math.abs(offset%60)),"hmm").format("HH:mm")));
------Edited--------
I found a better solution using moment.js. Just use moment().format('Z')
which gives the output :
+05:30

how to get local timezone on azure service

I have a service running on azure cloud. This service runs in every 1 min and picks some files from ftp server. These files have Datetime fields and not datetimeoffset, which when read by service become UTC dates. These FTp servers are in different timezone.
For example one of the ftp is in GMT timezone. Say file has date 12/5/2015 time 12:15. This is read by service as UTC(because no timezone received) and stored in database as 12/5/2015: 12:15:00 +0:00, while it should be
12/5/2015: 11:15:00 +0:00.
I still want to save date in database as UTC, need a way to get these ftp timezones, so I can parse date correctly.
The problem is we can't make any changes in file.
Is there any way cloud sevice can get timezone for these FTP?
There's nothing Azure specific here for what you want, but you can roll your own solution.
You'd have to do some fancy stuff to guess the timezone of an FTP server, which would involve doing a DNS lookup of the server to figure out it's IP address, mapping that IP address to a city, and looking up the city's Time Zone. You could do that but it would be error prone.
There's an easier and more reliable option. It sounds like you your list of FTP servers is fairly static. You can just create a lookup table that says which timezone each FTP server is in, and use that table to figure out which timezone offset you should use.
Best practice: Server-side code should never depend on the time zone or culture settings of the server that is hosting the code. Instead, these concerns should be addressed in the code itself.
For example, assuming your service is written in C# / .NET, you might have code like this:
string s = "12/5/2015 12:15 PM"; // from the file
DateTime dt = DateTime.Parse(s);
DateTime utc = dt.ToUniversalTime();
The above code relies on the server's local time zone during the ToUniversalTime function. It also relies on the server's culture during the Parse function.
Instead, you should have knowledge of the time zone and culture of the input file. For example:
string s = "12/5/2015 12:15 PM"; // from the file
DateTime dt = DateTime.ParseExact(s, "M/d/yyyy h:mm tt", CultureInfo.InvariantCulture);
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time");
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt, tz);
This code supplies the CET/CEST time zone, and also provides an exact input format using the invariant culture.
Late post, but thought I would post my solution to help anyone else:
TimeZone localZone = TimeZone.CurrentTimeZone;
var cetZone = TimeZoneInfo.FindSystemTimeZoneById(localZone.StandardName);
var cetTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, cetZone);
DateCreated = Convert.ToDateTime(cetTime.ToString());
In my instance, the localZone.StandardName gives me "South African Standard Time", which I believe is GMT+2.
Hope this helps someone else out!
Cheers

Resources