Is there a primitive type for DateTime in Bixby? - bixby

My model will optionally take a time in many utterances.
So examples...
add wet diaper. <-------- assumes current time
add wet diaper at 4:00 PM
add bottle at noon
What would be the best way to model 4 PM/AM so that in my actions I can collect the time?

You'll want to define an action that accepts an optional input, and make sure the type is 'DateTimeExpression'. In your NL training, you can say things like 'do this thing at 4PM' or 'do this thing'. Both are valid because you made the date optional. In your javascript, check to see if the user said a date. If they did, use it. If not, you can default to now. Refer to this link for grabbing the time from javascript. The date api will parse dates to the device's local time by default (can be overridden).
In your action
input (searchDate) {
type (time.DateTimeExpression)
min(Optional) max (One)
}
In your javascript
var currentTime = dates.ZonedDateTime.now().getDateTime();
if (searchDate)
currentTime = //Grab the date from searchDate.
Use this for reference.

There is no primitive type DateTime, but there is a viv.time library you can use, and in fact there is viv.time.DateTimeExpression concept you can use.
viv.time.DateTimeExpression not only handles "4 AM" but also "tomorrow 4 AM", you can read more here. I would say it is one of the most commonly used library concepts.

Related

What is equivalent of TimeZoneInfo.ConvertTime in NodaTime?

I want to use the NodaTime library to convert the date from one timezone to another like this.
string fromSystemTimeZoneId = "GMT Standard Time";
string toSystemTimeZoneId = "Central Standard Time";
TimeZoneInfo fromTimeZone = TimeZoneInfo.FindSystemTimeZoneById(fromSystemTimeZoneId);
TimeZoneInfo toTimeZone = TimeZoneInfo.FindSystemTimeZoneById(toSystemTimeZoneId);
var convertedTime = TimeZoneInfo.ConvertTime(inputDateTime, fromTimeZone, toTimeZone);
The above code works perfectly fine for me, But now I want to use IANA standard time zone (like Europe/London and America/Chicago) in place of windows OS-provided time zone ids.
I am using .net 4.7.2 and cannot upgrade the framework due to some limitations.
I have gone through this answer, But I am looking for simple few lines of code nothing complicated.
But I am looking for simple few lines of code nothing complicated.
But you're trying to do something complicated. Noda Time makes everything explicit, which means it's clear exactly what's going on - at the cost of being a little more verbose.
DateTime has no concept of a time zone itself (other than for the special cases where the Kind is Utc or Local). So TimeZoneInfo.ConvertTime has to:
Consider what instant in time is represented by inputDateTime in fromTimeZone
Work out what that instant in time looks like in outputDateTime
In Noda Time, those are are two separate operations, if you want to start and end with a LocalDateTime:
LocalDateTime inputDateTime = ...;
DateTimeZone fromTimeZone = ...;
DateTimeZone toTimeZone = ...;
// There are options for how this conversion is performed, as noted in other questions
ZonedDateTime inputDateTimeInFromTimeZone = inputDateTime.InZoneLeniently(fromTimeZone);
// This conversion is always unambiguous, because ZonedDateTime unambiguously
// refers to a single instant in time
ZonedDateTime inputDateTimeInToTimeZone = inputDateTimeInFromTimeZone.WithZone(toTimeZone);
LocalDateTime localPart = inputDateTimeInToTimeZone.LocalDateTime;
So that's basically the equivalent conversion - but you need to be explicit about how you want to handle skipped/ambiguous inputs. If you want everything in your app to use the same conversion, you can wrap that in a method that looks just like TimeZoneInfo.ConvertTime. But why not just keep things in a ZonedDateTime instead of LocalDateTime to start with? Then you don't get into the ambiguous position - other than potentially when converting user input (which is entirely separate from converting from one time zone to another).

Selecting appropriate Noda time structures

I have the following data which i was querying with .net time and ran into issues with timezones and spans. I was recommended to use Noda Time.
"MarketStates": {
"dataTimeZone": "America/New_York",
"monday": [
{
"start": "04:00:00",
"end": "09:30:00",
"state": "premarket"
},
{
"start": "09:30:00",
"end": "16:00:00",
"state": "market"
}
],
"holidays": [
"1/1/1998",
"1/1/1999",
"1/1/2001"
],
"earlyCloses": {
"7/3/2000": "13:00:00",
"7/3/2001": "13:00:00"
}
}
I am writing a function IsMarketOpen providing a time to test against, and the above MarketStates json database - it returns true if the current time is during market open and false if a holiday or earlyClose.
For the market states (monday above) I will use a LocalTime.
For the earlyCloses I plan to use ZonedDateTime.
For the passed time into this method, I will use a ZonedDateTime.
For holidays would I need to keep the timezone? I cannot find a ZonedDate, only OffsetDate or LocalDate?
In summary, should I keep everything ZonedDateTime (since i have the time zone specified in the json database snippet above), or use a LocalDateTime and then perform the conversion/testing at that point?
Please bear with me for the above question I didn't realize that time is actually so hard and need guidance for structure selection, I will adapt as per comments if extra context is needed. Thank you.
Your earlyCloses looks like it's really a Dictionary<LocalDate, LocalTime>, and holidays is a List<LocalDate>. (As a side note, it's pretty awful that it's not using ISO-8601 for the date format... I can't tell whether those early closes are July 3rd or March 7th.)
The time zone is specified by dataTimeZone, but I'd suggest keeping it as a string in the model, and converting it to a DateTimeZone when you need to.
The thrust of what I'm saying is that I'd encourage you to make the values in your direct model (loaded from JSON and saved to JSON) match what's actually stored in the JSON. You could have a wrapper around that model which (for example) converted the early closes into ZonedDateTime values... but I've generally found it really useful to keep the "plain model" simple, so you can immediately guess the representation in the JSON just from looking at it.

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.

Are Alexa skill dates the same in the Service Simulator and the Echo?

My Alexa node.js skill involves getting the current date using "new Date()". In the Service Simulator the date returned is UTC. But I need the time in "America/New_York" -- my skill is local to New York. So I can convert the time zone, no problem. But I'm wondering whether this will get the same result when I deploy the skill. That is, does the Date() function on the actual Service convert to local time from UTC? If it does, then I will need some way of determining in my code whether I am in the Service Simulator or the actual Service, and converting to New York time in my accordingly.
Thank you.
From the documentation for Date
If no arguments are provided, the constructor creates a JavaScript Date object for the current date and time according to system settings.
So depending on the system settings the timezones can be different.
To overcome this you can use UTC date everywhere and then simply convert the timezone where needed.
// date with some timezone depending on system
let date = new Date();
// date in UTC
let utcDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
Note: utcDate will still be in the system timezone, but the actual value it holds will represent the correct date and time in UTC.

NodaTime - Errors after time switch

Yesterday Uruguay changed their clocks, and now I keep seeing exceptions when converting specific times for their timezone:
ERROR Exception: - DateTime ConvertTimeToUtc(DateTime, String) (05/10/2014 02:31:00, America/Montevideo)
NodaTime.SkippedTimeException: Specified argument was out of the range of valid values.
Parameter name: Local time 05/10/2014 02:31:00 is invalid in time zone America/Montevideo
I understand how a local time can be invalid:
"For example, suppose the time zone goes forward at 2am, so the second after 01:59:59 becomes 03:00:00. In that case, local times such as 02:30:00 never occur."
However, what I don't understand (and I probably need more coffee), is why NodaTime is not accounting for this? Should it not be aware that 02:31 is now an invalid local time - or should I be doing additional handling to account for this?
Functions I'm calling:
var timeZone = DateTimeZoneProviders.Tzdb[timezoneName];
var localTime = LocalDateTime.FromDateTime(timeToConvert).InZoneStrictly(timeZone);;
return DateTime.SpecifyKind(localTime.ToDateTimeUtc(), DateTimeKind.Utc);
Yes, it is aware that it's an invalid local time - which is why when you specifically ask it to convert that local time into UTC, it throws an exception. It's roughly equivalent to calling Math.sqrt(-1).
The InZoneStrictly call you're making specifically throws an exception on either ambiguous or skipped times. If you use InZoneLeniently you won't get an exception, but it may not give you the result you want. Or, you could use LocalDateTime.InZone(DateTimeZone, ZoneLocalMappingResolver) which will allow you to map invalid local date/time values however you want.
As side-notes:
Your localTime variable is a ZonedDateTime, so the name is a bit misleading
You don't need to call SpecifyKind - ToDateTimeUtc will always return a DateTime with a kind of Utc, hence the name.

Resources