How to validate that a property with a DATE-TIME value must have a TZID parameter? - icalendar

Section 3.2.19 of RFC 5545 says that a property with a DATE-TIME value must specify a TZID parameter in this situation:
The parameter [TZID] MUST be specified on properties with a DATE-TIME value if the DATE-TIME is not either a UTC or a "floating" time.
The DTSTART property has a DATE-TIME value. Here is an instance:
DTSTART:19970714T133000
Is that a valid property with a "floating" time? Or, is it an invalid property with a "floating" time that erroneously forgot to include the TZID parameter?
When validating an iCalendar file, how do I distinguish between a valid property with a value that is a "floating" time versus an invalid property with a value that is a "floating" time and erroneously forgot to include the TZID parameter?

When validating an iCalendar stream, there is nothing to distinguish. It is always a floating time.
When constructing an iCalendar stream on the other hand, one should
first understand the 3 types defined at https://www.rfc-editor.org/rfc/rfc5545#section-3.3.5 ,
then decide which one is the most appropriate in their application specific context.
finally, based upon 2 (i.e. choice between UTC, local with tz or floating), apply the rule that you referenced in your post.
Please note that client support for floating time is generally poor and unpredictable so you should avoid generating it if you can.

Related

How to use a date in a logical condition in Dialogflow CX

I am brand new to Dialogflow CX and am having trouble figuring out how to use a date in a condition. I want to require that a birthdate be entered and be greater than 2000-01-01. I have tried
$intent.params.dob.resolved > 2005-01-01
with and without quotes, but it does not work (always false). I discovered that $intent.params.dob.original > "1/1/01" is resolved as True for all dates, so that is of no help.
Is there a way that works?
To achieve your described use case, you can utilize the condition route or conditional response to return a response according to the condition. Here is a condition you may use:
$intent.params.birthdate.resolved.year > 2000 OR
($intent.params.birthdate.resolved.year = 2000 AND
$intent.params.birthdate.resolved.month > 1) OR
($intent.params.birthdate.resolved.year = 2000 AND
$intent.params.birthdate.resolved.month = 1 AND
$intent.params.birthdate.resolved.day > 1)
Here are examples for your reference:
A. Using the condition in the Conditional Response
B. Using the condition as the Condition Route:
Please note that the birthdate parameter isn’t a string parameter. It is composed of year, month, and day sub-parameters so it is appropriate to utilize them for your use case. Also, note that dates are in ISO-8601 format. For more information, you can refer to the System Entities documentation.
Here are the following results using the condition defined in the conditional response:
When the user enters the same year but not January 1st
When the user enters an invalid date
When the user enters a previous date from 2000-01-01
When the user enters a valid date and latest from 2000-01-01
I guess $intent.params.dob.resolved returns a string, so you need to build a date object firstly, and then compare it with your date.
I encountered a similar problem a few weeks ago. Thing is, Dialogflow actually defaults to string parameters: this means that every value entered as a parameter will (by default) be a string, surrounded by "quotes".
To operate comparisons between dates you'd want to compare integers/numbers, and I think the best way to do so is to take advantage of date system entities.
For example, the system entity
#sys.date
allows you to match a date inserted by the user. Then the best part is, in your condition, you can even manage the date by referencing sub-parts. Here is an example:
if $intent.params.dob.year <= 2005 AND $intent.params.dob.month <= 04:
I'm sorry, you're too young to use this service!
endif
Also, on a side note, "intent parameters" actually become "session parameters" as soon as Dialogflow makes a step from the state in which the parameter was set to another page.
This means that if you set the parameter dob when the user says "I was born on the thirteen of July, 2004" and then you go on to a new page, that parameter will only be accessible as $session.params.dob (and session parameters don't have a "resolved value", they are resolved by default).
So, to recap. Make sure you're using the system date entity. Make conditions for all the parts of the date you need to verify (year, month, day) and try to use your parameter as a session parameter.
I hope at least some of what I wrote can help you, happy bot-building!

Clojure: creating a date-time object for the JDBC

I created my PostgreSQL table with a column:
updated_at timestamp(0) with time zone
I'm using clojure.java-time but I can't create a string (or should be an object?) to set the current date-time. I tried with:
(time/format "yyyy-MM-dd HH:ss" (time/local-date-time))
and with that string I tried:
(db/update-answer! {:updated_at "2019-12-25 14:08", :id 102, :answer "Foo"}
but the JDBC tells me that the field "updated_at" doesn't have a valid type. As far as I understand the JDBC is still using the old java API for handle the dates and time zones and not the new in JDK 8. So, in summary I don't know how to create a string or an object valid for Postgresql time-stamp column using clojure.java-time.
Someone advises me about extending the JDBC protocol, I'm reading about it but for now I'm just looking for a way to create a valid object and finish this update.
UPDATED
After followed this page I could give format to Instant with:
(ns zentaur.hiccup.helpers-view
(:require [clojure.tools.logging :as log]
[java-time :as jt])
(:import [java.time ZoneId]))
(defn format-date [date]
(log/info (str ">>> DATE >>>>> " date "und type >>> " (type date)))
(jt/format "yyyy-MM-dd HH:mm" (.atZone date (ZoneId/systemDefault))))
(Java syntax, not Clojure)
tl;dr
Use objects, not Strings. Use java.time classes in Java, never the legacy date-time classes.
myPreparedStatement
.setObject(
… ,
OffsetDateTime.now()
)
Even better would be a trigger to do this automatically.
in summary I don't know how to create … an object valid for Postgresql time-stamp column using clojure.java-time.
Call OffsetDateTime.now() to get a java.time.OffsetDateTime object holding the current moment.
Use a database column of type TIMESTAMP WITH TIME ZONE rather than TIMESTAMP (short for TIMESTAMP WITHOUT TIME ZONE).
Moments
set the current date-time
If you want to track moments, specific points on the timeline, you are using the wrong data type.
You are using TIMESTAMP which is short for TIMESTAMP WITHOUT TIME ZONE. This type lacks any concept of time zone or offset-from-UTC. So this type cannot track moments. I suggest you avoid the short version of this type name in the future, to make your SQL clear. See Postgres doc.
You should be defining your column as TIMESTAMP WITH TIME ZONE. Postgres handles this type by always saving the moment as seen in UTC. Any provided time zone or offset in the input is used to adjust to UTC. Likewise, when retrieved, your value is always in UTC, an offset of zero hours-minutes-seconds.
Beware of middleware and tools that dynamically apply some time zone to the retrieved value. This clouds matters, creating the illusion that the value was stored in that time zone. The value was actually stored in UTC, always in UTC in Postgres.
Smart objects, not dumb strings
but I can't create a string (or should be an object?) to set the current date-time.
Don’t.
You should be exchanging objects between Java and Postgres, rather than mere strings. This avoids the time-zone injection problem mentioned above.
As of JDBC 4.2, you can exchange modern java.time objects with the database. Never use the legacy types such as Calendar, GregorianCalendar, java.util.Date, java.sql.Date, java.sql.Timestamp, and so on. These classes were terribly flawed, designed by people who did not understand date-time handling. They were supplanted as of the adoption of JSR 310.
Capture the current moment as an OffsetDateTime. Your JDBC driver might support Instant & ZonedDateTime but those types are optional, as seen in graphic table above. In contrast, JDBC requires support for OffsetDateTime.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;
The explicit use of ZoneOffset.UTC in code above is not strictly required. If omitted, your JVM’s current default offset will be applied implicitly. Your JDBC driver and/or Postgres will adjust to UTC as discussed earlier above. My own preference for the sake of debugging/logging is to specify UTC so I can see the value as it will eventually be stored in the database.
And retrieval.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Default value
If you are simply recording the moment whenever a row is updated, no need to do that in your SQL. I suggest you write a trigger to be called whenever a row in that table is updated. Then you are guaranteed the value will be written no matter the mechanism by which the row was updated. And less to worry about when writing your SQL statements.

How can you represent a Date object that should ignore the time?

We are defining a microservice that returns a timestamp in the combined date-and-time ISO 8601 format which is returned to our iOS client that's written in Swift. In our client, this is converted to a Date object.
The issue is one of the feeding sources of our microservice represents their date/times as two separate fields which we must combine into the complete ISO format. However, the time portion may be null so we have to substitute in 'T00:00:00Z'.
The problem is we need a way to communicate to the Swift side that the timestamp didn't have an original time value so it should be read in relative to GST, not the local timezone as one would normally do, and it should only ever be displayed in the UI as a date-only.
That said, what is the proper way to flag a Date object as being Date-only? Our current solution is a paired xIsDateOnly boolean on the model, but that just seems verbose. Does the Date object have any such mechanism/indication? I'm guessing not because a date without a time doesn't actually make sense as dates are based on 12am in a particular timezone, usually implied to be the one the user is in.
You're right, the Foundation (NS)Date object is really a timestamp, representing a specific moment in time. While it doesn't let you just specify a particular day, it does have the advantage of being the same no matter what calendar is in use.
To represent something like "June 3, 2014", you can use a DateComponents object. This lets you specify month, day, year, etc, without a time of day, relative to a particular calendar.

Tableau - Dynamic Parameter Reference

I have a series of parameters in Tableau corresponding to every month in the coming years. The parameter names are all in the format Name - YYYY-MM-DD where YYYY-MM-DD is the corresponding beginning of the month. I would like to reference the parameter using the current month value (e.g. 2017-11-01).
How can I reference a parameter using something like the following:
["Name "+DATEFUNCTION()]
where DATEFUNCTION() will create the date in the appropriate format. However, this clearly does not work.
Referencing parameter name dynamically is not possible.
You can either try to implement your logic of pulling data out of parameters as a single calculated field or use a secondary datasource containing Date,Value,DummyLinkToPrimary fields and filter it on date.

What does a period RDATE mean?

RFC 5545 allows the RDATE property to have a data type of PERIOD. What are the semantics of this data type? As far as I can tell, it's unspecified. Does it change the duration of the event? What if it's on a time zone change, which can't have a duration?
Though I agree with you that RFC5545 leaves too many things for interpretation, in this occasion it seems to be giving some guidance for combinationss of PERIOD and RDATE:
For example, recurrence instances of a nominal
duration of one day will have an exact duration of more or less
than 24 hours on a day where a time zone shift occurs. The
duration of a specific recurrence may be modified in an exception
component or simply by using an "RDATE" property of PERIOD value
type.
and
When the combination of the "RRULE" and "RDATE" properties in a
recurring component produces multiple instances having the same
start DATE-TIME value, they should be collapsed to, and
considered as, a single instance. If the "RDATE" property is
specified as a PERIOD value the duration of the recurrence
instance will be the one specified by the "RDATE" property, and
not the duration of the recurrence instance defined by the
"DTSTART" property.
and example is available:
RDATE;VALUE=PERIOD:19960403T020000Z/19960403T040000Z,
19960404T010000Z/PT3H