#mui/x-date-pickers UTC always, please - material-ui

Using #mui/x-date-pickers I need to both display and edit in UTC. My stored data is also in UTC. I can wrap the value in a render function to force-display it in the format I need, but then upon edit the date is shown in my locale! I feel like there should be an option to say, "Just let me show and edit in UTC." Any help greatly appreciated. I can't believe this hasn't come up for scientific apps before.
import { AdapterDateFns } from '#mui/x-date-pickers/AdapterDateFns';
import { DateTimePicker } from '#mui/x-date-pickers/DateTimePicker';
import { LocalizationProvider } from '#mui/x-date-pickers/LocalizationProvider';
const dateFormat = 'yyyy-MM-dd HH:mm:ss';
const inputMask = '____-__-__ __:__:__';
const views = ['year', 'month', 'day', 'hours', 'minutes', 'seconds'];
const renderUTC = new Date(date).toISOString().replace('T', ' ').substring(0, 19);
...render returning:
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DateTimePicker
value={renderUTC(value)}
...

Ran into the same issue. My workaround was to use the getTimezoneOffset() to offset local to UTC before it goes into DateTimePicker as value and offset UTC to local after it comes out of DateTimePicker through onChange.
That way the dateTime in DateTimePicker widget appears same as the UTC dateTime even though it is in locale.
const offset = (utcTime) => {
const tzoffset = utcTime.getTimezoneOffset() * 60000
const localTime = new Date(utcTime.getTime() + tzoffset)
return localTime
}

Using insight from #bikesh-rana here is a complete solution.
This is a <DateTimePicker using Formik as well. Helper functions:
const getTimezoneOffset = value => value.getTimezoneOffset() * 60000;
const makeLocalAppearUTC = value => {
const dateTime = new Date(value);
const utcFromLocal = new Date(dateTime.getTime() + getTimezoneOffset(dateTime));
return utcFromLocal;
};
const localToUTC = dateTime => {
const utcFromLocal = new Date(dateTime.getTime() - getTimezoneOffset(dateTime));
return utcFromLocal;
};
And, in the <DateTimePicker:
value={makeLocalAppearUTC(field.value)}
onChange={value => field.onChange({ target: { value: localToUTC(value), id } })}
Thank you for the insight #bikesh-rana!

Related

Flutter how to subtract time from other time

I have 2 times which I need to do subtract and I am almost close but there is one big issue
I have 2 times in string-like 10:00AM and 10:00PM
And my code is this
var df = DateFormat("hh:mm");
var durationStart = DateFormat('HH:mm').format(df.parse(10:00AM));
var durationEnd = DateFormat('HH:mm').format(df.parse(10:00PM));
print('durationStart ${durationStart}');
print('durationEnd ${durationEnd}');
var Startparts = durationStart.split(':');
var startDurationSet = Duration(hours: int.parse(Startparts[0].trim()), minutes: int.parse(Startparts[1].trim()));
var Endparts = durationEnd.split(':');
var endDurationSet = Duration(hours: int.parse(Endparts[0].trim()), minutes: int.parse(Endparts[1].trim()));
print('startDurationSet ${startDurationSet}');
var result = Duration(hours: int.parse(Endparts[0].trim()) - int.parse(Startparts[0].trim()) , minutes: int.parse(Startparts[1].trim()) - int.parse(Endparts[1].trim()));
print('result ${result.toString().replaceAll('-', '')}');
So I have 2 times one is startTime and one is End time. I simply need a difference between hours. for example, I have 10:00Am and 01:00PM i need 3hours but it's showing 9hours. But what I am receiving is if I have 10:00AM and 10:00pm it's showing 0 hours but its needs to show 12. Same
It is easy if you can get your start and end date in DateTime properly
Hint, I use "hh:mma" since that is your original format => "10:00AM"
If I use "HH:mm" like you do, i'll always get the same time since it doesn't parse the AM/PM after the 10:00
// Get your time in term of date time
DateTime startDate = DateFormat("hh:mma").parse("10:00AM");
DateTime endDate = DateFormat("hh:mma").parse("10:00PM");
// Get the Duration using the diferrence method
Duration dif = endDate.difference(startDate);
// Print the result in any format you want
print(dif.toString(); // 12:00:00.000000
print(dif.inHours); // 12
Are you looking for something like this?
TimeOfDay _calcTimeOfDay(int hour, int minute) {
if (minute > 60) {
minute = (minute % 60);
hour += 1;
}
return TimeOfDay(hour: hour, minute: minute);
}
The problem is if you have hour=24 and minute=75 then the hour would be 25, which is not a valid hour.
Not sure I fully understand the question, maybe if you can provide more info.
What you need to add on your DateFormat is the code for am/pm marker: a. Using either format hh:mma or h:ma should work.
You can then use DateTime.difference() to calculate the time variance from durationStart and durationEnd. Here's a sample that you can run on DartPad.
import 'package:intl/intl.dart';
void main() {
/// Set the format that of the Date/Time that like to parse
/// h - 12h in am/pm
/// m - minute in hour
/// a - am/pm marker
/// See more format here: https://pub.dev/documentation/intl/latest/intl/DateFormat-class.html
var dateFormat = DateFormat('h:ma');
DateTime durationStart = dateFormat.parse('10:00AM');
DateTime durationEnd = dateFormat.parse('10:00PM');
print('durationStart: $durationStart');
print('durationEnd: $durationEnd');
/// Fetch the difference using DateTime.difference()
/// https://api.flutter.dev/flutter/dart-core/DateTime/difference.html
print('difference: ${durationEnd.difference(durationStart).inHours}');
}
Use package
intl: ^0.17.0
import 'package:intl/intl.dart';
var dateFormat = DateFormat('h:ma');
DateTime durationStart = dateFormat.parse('10:00AM');
DateTime durationEnd = dateFormat.parse('1:00PM');
print('durationStart: $durationStart');
print('durationEnd: $durationEnd');
var differenceInHours = durationEnd.difference(durationStart).inHours;
print('difference: $differenceInHours hours');
I have created one class for you:
import 'package:intl/intl.dart';
class DateUtils {
static String getTimeDifference(String startTime, String endTime){
/// Set the format that of the Date/Time that like to parse
/// h - 12h in am/pm
/// m - minute in hour
/// a - am/pm marker
/// See more format here: https://pub.dev/documentation/intl/latest/intl/DateFormat-class.html
var dateFormat = DateFormat('h:ma');
DateTime durationStart = dateFormat.parse(startTime);
DateTime durationEnd = dateFormat.parse(endTime);
return '${durationEnd.difference(durationStart).inHours} hours';
}
}
How you can use:
void main() {
print("10:00PM, 10:30PM => " + DateUtils.getTimeDifference("10:00PM", "10:30PM"));
print("12:00AM, 04:00AM => " + DateUtils.getTimeDifference("12:00AM", "04:00AM"));
print("01:00AM, 03:00AM => " + DateUtils.getTimeDifference("01:00AM", "03:00AM"));
print("12:00AM, 06:00PM => " + DateUtils.getTimeDifference("12:00AM", "06:00PM"));
print("04:00PM, 03:00PM => " + DateUtils.getTimeDifference("04:00PM", "03:00PM"));
}
Output:
10:00PM, 10:30PM => 0 hours
12:00AM, 04:00AM => 4 hours
01:00AM, 03:00AM => 2 hours
12:00AM, 06:00PM => 18 hours
04:00PM, 03:00PM => -1 hours
Hope it will be helpful.

How can we identify time section in datetime flutter

I will receive DateTime in UTC format from API and I need to convert the DateTime to local time zone based on the condition.
We have toLocal() method to change the time based on the device time zone.
condition: 23-4-2021 // no need to change it to toLocal()
23-4-2021 00:00:00 // no need to change it to toLocal()
23-4-2021 10:30:34 // need to change it to toLocal()
If we have time in the DateTime then only we have to change it in local time.
DateTime utcToDateTimeLocal(DateTime value) {
return value.toLocal();
}
Thanks!
Something like this maybe ?
DateTime utcToDateTimeLocal(DateTime value) {
if (value.hour!=0 || value.minute!=0 || value.second!=0){
return value.toLocal();
}
return value;
}
Here is quick solution that work for me.
You can get time (or any format) by DateFormat class
In your case
dateTime = '23-4-2021 10:30:34'
final format = DateFormat('HH:mm a');
final clockString = format.format(dateTime);
you will get // 10:30 AM
DateTime utcToDateTimeLocal(DateTime value) {
var dateFormat =
DateFormat("dd-mm-yyyy hh:mm a"); // you can change the format here
var utcDate =
dateFormat.format(DateTime.parse(value.toString())); // pass the UTC time here
var localDate = dateFormat.parse(utcDate, true).toLocal().toString();
return DateTime.parse(localDate);
}

sap.ui.core.format.DateFormat.format give wrong date

For one Client, and only when switch the browser to english, the following code:
convertTimeToDate: function(dateobj) {
if ((dateobj == undefined) || (dateobj == null)) {
return "";
}
var dateFormat = sap.ui.core.format.DateFormat.getDateInstance({
pattern: "dd. MMM YYYY"
});
var dateFormatted = dateFormat.format(dateobj);
return dateFormatted;
},
returns when inputing the highdate '9999-12-31' the datestring '31. Dec 10000' what could be the problem? It is reproducible only on the maschine of this one person, but for her it happens ALWAYS.
To avoid problems with timezones, especially in UI5 apps in HR, I decided to send/receive dates and times in ISO format as strings in my recent developments, it guarantees that a user in browser will see the same value as in the SAP back-end system.
To make sure you use these values both for input and output it is recommended to implement a Custom Data Type.
Suppose you have an sap.m.DateRangeSelection which accepts JavaScript Date objects as dateValue and secondDateValue, and you want bind these properties to a model, where properties like startDate and endDate are date strings of yyyy-MM-dd pattern.
In this case a sample custom data type can be like this:
sap.ui.define([
"sap/ui/model/SimpleType",
"sap/ui/core/format/DateFormat"
], function(SimpleType, DateFormat) {
"use strict";
return SimpleType.extend("MyProject.model.ISODateType", {
/**
* Converts JavaScript Date object to ISO date string
*
* #public
* #param {string} sISO the ISO value of the formatted property
* #returns {string}
*/parseValue: function(oDate) {
var oFormat = DateFormat.getDateInstance({
pattern: "yyyy-MM-dd"
});
return oFormat.format(oDate);
},
/**
* Produces JavaScript Date object from ISO date string
*
* #public
* #param {string} sISO the ISO value of the formatted property
* #returns {string}
*/
formatValue: function(sValue) {
return new Date(sValue);
},
/**
* Validates the value to be parsed (should be ISO date string)
*
* #public
* no client side validation is required
* #returns {boolean} true
*/
validateValue: function(sValue) {
var sPattern = /(\d{4})-(\d{2})-(\d{2})/;
return sValue.match(sPattern);
}
});
});
And the binding in an XML View can look like this:
<DateRangeSelection
width="30%"
dateValue="{
path: '/startDate',
type: 'MyProject.model.ISODateType'
}"
secondDateValue="{
path: '/endDate',
type: 'MyProject.model.ISODateType'
}"
change="onDateIntervalChange"/>
I was plagued by the same 10k date. My pattern was {pattern: 'MMMM Y'}. Changing it to {pattern: 'MMMM yyyy'} solved the problem. I cannot find any documents on the difference between 'Y' and 'y' though.
just an idea: the user did something (whatever) in his browser and timezone is somehow different for him/her. did you try passing a fixed timezone during fomatting? it looks like some seconds are added .. maybe some converting offset or whatever.
https://openui5.hana.ondemand.com/#/api/sap.ui.core.format.DateFormat/methods/sap.ui.core.format.DateFormat.getDateInstance
#since 1.34.0 contains pattern symbols (e.g. "yMMMd" or "Hms") which will be converted into the pattern in the used locale, which matches the wanted symbols best. The symbols must be in canonical order, that is: Era (G), Year (y/Y), Quarter (q/Q), Month (M/L), Week (w/W), Day-Of-Week (E/e/c), Day (d/D), Hour (h/H/k/K/j/J), Minute (m), Second (s), Timezone (z/Z/v/V/O/X/x) See http://unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
something like: https://gist.github.com/bvanzyl/b3b64306a7363f0b3e043608b48d8326
formatDateStr: function(data){
if(data === null || data === undefined){
return data;
}else{
var oDate = new Date(data);
var iLocalTime = oDate.getTime();
// Berlin timezone = UTC+1 = 1hr = 60min ahead
// 60min * 60000 for time in milliseconds
var iBerlinOffset = 60 * 60000;
var iLocalOffset = oDate.getTimezoneOffset() * 60000;
var iBerlinTime = iLocalTime + iLocalOffset + iBerlinOffset;
oDate.setTime(iBerlinTime);
var dateFormat = sap.ui.core.format.DateFormat.getDateInstance({pattern : "MMM, dd YYYY" });
var dateFormatted = dateFormat.format(oDate);
return dateFormatted;
}
}
};

How to extract day, month, and year from date returned by QML Calender?

The Calendar clicked signal returns a date as follows:
2015-11-13T00:00:00
However, I would like to have a date formatted like this:
Fri Nov 13 2015
This is what I tried:
onSelectedDateChanged:
{
calender.visible = false;
selectedDate = selectedDate.toLocaleTimeString(Qt.LocalDate, Locale.ShortFormat);
textOfSelectedDate.text = Date.fromLocaleTimeString(Qt.LocalDate, selectedDate, Locale.ShortFormat)}
}
textOfSelectedDate is the id of the text box where this date will be displayed.
How can I extract day, month, and year in a desired format from Date returned by Calender?
QML's date type extends Javascript's Date. Thus you can do:
onSelectedDateChanged: {
const day = selectedDate.getDate();
const month = selectedDate.getMonth() + 1; //assuming you want 1..12, getMonth()'s return value is zero-based!
const year = selectedDate.getFullYear();
...
}
First of all, date is similar to JS date type. So you can use all its functions, like getDate() etc. See it here
Also, you can use Qt.formatDate() object to format the result. In your case it can be as follows:
onClicked: {
console.log(Qt.formatDate(date,"ddd MMM d yyyy"))
}

How to select a calendar week in SAPUI5?

I am searching for a way to select just a calendar week with a DatePicker.
Is there a way to configure that control in a way, that it allows to pick a week and sends a DateTime element out of this week?
I detected the following entry with a list of format options, but week formatting seems not working:
http://scn.sap.com/community/developer-center/front-end/blog/2013/04/28/working-with-odata-dates
This code seems not working:
new sap.m.DatePicker({
value : {
path : "DateTime",
type : new sap.ui.model.type.Date({pattern: "w yy"})
}
}),
The binding is to OData property DateTime of type Edm:DateTime
Few things to be noticed:
Though SAPUI5 says it supports weeks in year, it doesn't currently! //I tested
why? in DateFormat.js file of SAPUI5
case "weekInYear":
sWeek = "";
//TODO getWeek does not exist on Date object
//-> this is a preparation for a future or custom week support
if (oDate.getWeek) {
sWeek += oDate.getWeek();
}
aBuffer.push(jQuery.sap.padLeft(sWeek, "0", oPart.iDigits));
break;
As you can see, its in TODO list!!
Workaround? Yes :
jQuery.sap.require("sap.ui.core.format.DateFormat");
//define getWeek function
Date.prototype.getWeek = function () {
var d = new Date(+this);
d.setHours(0, 0, 0);
d.setDate(d.getDate() + 4 - (d.getDay() || 7));
return Math.ceil((((d - new Date(d.getFullYear(), 0, 1)) / 8.64e7) + 1) / 7);
};
var oDateFormat = sap.ui.core.format.DateFormat.getDateInstance({
pattern: "w y"
});
var oDatePicker = new sap.m.DatePicker({
dateValue: new Date(),
displayFormat: "w y"
})
JSBin code piece is here