Hello! This article is a continuation of a series of articles devoted to the development of applications for the Sailfish OS mobile platform. This time we will discuss the features of working with dates and time zones in QML. We will begin the article with a description of the problem itself, and then we will go over how to solve it.
Description of the problem
When developing Sailfish OS applications, quite often in one form or another you will have to work with dates and time (as, indeed, when developing for any other platform). Sailfish OS uses components such as
DatePickerDialog and
TimePickerDialog to specify the date and time. Internally, they use the
Date QML object inherited from the standard JavaScript
Date object, which does not support the ability to create a date and time with a time zone other than UTC or local, to control the date and time. The
Date object simply has no constructor and methods for this.
new Date(); new Date(value); new Date(dateString); new Date(year, month[, day[, hour[, minute[, second[, millisecond]]]]]);
It would seem that a third constructor from the list should help here, if you pass it a string with the date, time and offset relative to UTC, but no. The time zone of the object will still be local, and not the one specified in the offset.
new Date('Jan 30 2017 10:00:00 GMT+0700')
You may ask: “Why use time zones at all? Why it’s impossible to manage with time in UTC? ”And I will answer you: yes, sometimes time zones do not make sense. Just use the date and time. For example, if your working day starts at 9:00, then you hardly expect your colleague from Kamchatka to start working at 18:00. However, in the case of regular events occurring at the same time in different time zones, the time zone is still needed. For example, the daily discussion of the current work on the project starts at 10:00 for you and at 19:00 for your colleagues in Kamchatka.
')
One of the solutions to the problem of creating a date and time with the installation of a time zone was the use of one third-party libraries:
timezone-js and
moment.js . But they turned out to be unsuitable, because
DatePickerDialog and
TimePickerDialog do not know anything about these libraries, and inside they actively use the standard
Date , which is incompatible with objects created using
timezone-js and
moment.js . As a result, two other solutions were developed.
Decision number 1
The first solution that occurred to us is to create our own JavaScript object to manage the date and time. Such an object should allow storing the date, time and information about the time zone, and most importantly, changing the date and time using the Sailfish OS components
DatePickerDialog and
TimePickerDialog , without affecting the time zone.
To create your own JavaScript object, you need to define a constructor function in a separate JavaScript file.
The constructor function accepts a string of the form “yyyy-MM-ddTHH: mm: ssZ”, where Z is an offset relative to UTC of the form “[+ -] HH: mm”, ISO 8601 standard. A
Date object is created from part of the string and assigned to the
dateTime property. This property will contain information about the date and time, excluding the time zone. The rest of the string, containing the offset relative to UTC, is stored in a separate property
utcOffset . Now we can create an object that will contain information about the date, time and time zone.
var myDateTime = new CustomDateTime("2016-12-22T13:40:00+05:00"); print(myDateTime.dateTime);
Add a method to our object that returns the date and time in the same format “yyyy-MM-ddTHH: mm: ssZ”.
Often, applications that work with date and time need to display the corresponding values. We, as developers, must ensure that all users will display the date and time correctly in accordance with the current locale. To do this, we add methods to our JavaScript object that return strings with a language-dependent representation of the date and time.
Thus, we have an object that stores and allows editing date, time, and time zone information, is created using a string in a specific format, can return a string in the same format, as well as formatted strings in the current locale. Such an object will easily allow us to operate with date and time in the required time zone.
Consider an example of using the
CustomDateTime object.
The example contains the
ValueButton components for editing the date and time.
Clicking on one component opens
DatePickerDialog , on clicking on the second
component -
TimePickerDialog . The
ValueButton component for time editing is described in more detail. The
CustomDateTime object is created as a property of the
Page component and is used to display the date and time in the
ValueButton using the
value property and also to pass the values to the
DatePickerDialog and
TimePickerDialog , as described in the
onClicked event
handler . It also describes
how to get data from
DatePickerDialog and
TimePickerDialog and update the
dateTime property of the
CustomDateTime object.
So, a JavaScript object was created CustomDateTime, which allows you to store information about the date, time and time zone, as well as allowing you to edit the date and time using
DatePickerDialog and
TimePickerDialog .
The disadvantage of this solution is that the JavaScript object does not support binding properties. In the example, after changing the date or time (changing the
dateTime property of the
CustomDateTime object), the
value property of the
ValueButton object will not
update , i.e. visually there will be no changes on the screen, despite the fact that the
CustomDateTime object has
actually changed. This is because the
DateTime property of the
CustomDateTime object cannot be associated with the
value property of the
ValueButton object.
In those cases where the binding of properties does not matter, you can use the solution described above, but in other cases you need to refer to decision # 2.
Decision number 2
The second solution is to create your own QML component, in particular a component of type
QtObject .
QtObject is the most "lightweight" standard QML type, has no visual component and can be useful when creating a model object. And most importantly, QML components support binding properties. Rewrite the JavaScript object defined above into a QML component.
The code has become more concise, the constructor function and JavaScript methods of the object have been replaced with the properties inside
QtObject . Now, to create a new object, we need to use the standard QML syntax and define only one
dateTimeStringToSet property, all other properties will be calculated automatically, because the binding properties will work.
CustomDateTime { dateTimeStringToSet: "2017-01-15T13:45:00+05:00" }
We will rewrite the example above, using the
CustomDateTime QML object.
It is easy to see that the changes are not much. The property declaration has been replaced by the declaration of the
CustomDateTime QML component, and the
localeDateString and
localeTimeString properties are used instead of the
toLocaleDateString () and
toLocaleTimeString () functions . In all other respects, the code has not changed at all, but property binding is now working. Changing the
dateTime property of the
CustomDateTime object will update all the properties of the object and the
localeTimeString property in particular, which will update the appearance of the
ValueButton object.
Conclusion
As a result, a solution for managing the date, time, and time zone information was developed, supported by components for editing the date and time in Sailfish OS. The solution is to create your own QML component and use it as a model. Such an object allows you to store the date, time, and time zone, and also supports a mechanism for linking properties and can be used inside Sailfish OS of the
DatePickerDialog and
TimePickerDailog components for editing. The source code for this example is available on
GitHub .
The author: Ivan Shchitov