How to save flutter TimeOfDay to firebase? - firebase

I am working on a flutter application where I am showing a TimeRangepicker using this plugin: time_range_picker and I am getting TimeOfDay(09:00) + TimeOfDay(12:00) as a result by using this code:
onPressed: () async {
TimeRange result = await showTimeRangePicker(
use24HourFormat: false,
interval: Duration(minutes: 30),
context: context,
start: TimeOfDay(hour: 9, minute: 0),
end: TimeOfDay(hour: 12, minute: 0),
disabledTime: TimeRange(
startTime: TimeOfDay(hour: 23, minute: 0),
endTime: TimeOfDay(hour: 5, minute: 0)),
disabledColor: Colors.red.withOpacity(0.5),
strokeWidth: 4,
ticks: 24,
ticksOffset: -7,
ticksLength: 15,
ticksColor: Colors.grey,
labels: [
"12 pm",
"3 am",
"6 am",
"9 am",
"12 am",
"3 pm",
"6 pm",
"9 pm"
].asMap().entries.map((e) {
return ClockLabel.fromIndex(
idx: e.key, length: 8, text: e.value);
}).toList(),
labelOffset: 35,
rotateLabels: false,
padding: 60);
print("${result.startTime} + ${result.endTime}");
},
But the only problem is I can find an appropriate way to save this to firebase, I don't need date all I need is TimeOfDay.

There is no specific data type in Firestore for storing a time of day, so you'll have to map it to one of the existing types.
Some common mapping are:
Store the time of day as a string value, such as "07:55:00.000" (if you care up to millisecond precision)
Store the time of day as an offset from midnight, such as 28500 (as the number of seconds from midnight until 7:55 AM)
Store the time of day as a the time part of a fixed day in a Timestamp field. This is essentially a variant of the previous approach, with the offset being from the start of the epoch. Say that you pick the start of the epoch (January 1, 1970) as the fixed day, then the Timestamp's value would be 28500000 (in milliseconds).
All of these have valid use-case, so pick whichever one works best for the use-cases of your app.

In the common use case whereby only the hour and minute are required a simple map of these values will suffice.
Map timeOfDayToFirebase(TimeOfDay timeOfDay){
return {
'hour':timeOfDay.hour,
'minute':timeOfDay.minute
}
}
TimeOfDay firebaseToTimeOfDay(Map data){
return TimeOfDay(
hour: data['hour'],
minute: data['minute']);
}
var myTimeOfDayObject=TimeOfDay.now();
firebase.update({'time': timeOfDayToFirebase(myTimeOfDayObject)});
This way you don't have to worry about managing offsets, unintended locale changes and so forth.

You can use something like this
class ClassModel {
TimeOfDay time;
ClassModel({
required this.time,
});
Map<String, dynamic> toMap() {
return <String, dynamic>{
'time': (time.hour.toString() + "*" + time.minute.toString()),
};
}
factory ClassModel.fromMap(Map<String, dynamic> map) {
return ClassModel(
time: TimeOfDay(
hour: int.parse(map['time'].toString().split("*").first),
minute: int.parse(map['time'].toString().split("*").last)),
);
}
}

Related

Kotlin Realtime Firebase Post set autoincrement ID to database

I would like to save an Item to Firebase. When I save one Item, then my structure looks like i want to look, but I have problem with ID:
Trips
-My6qIbSx5dnSy2yScAr
date: "Feb 20, 2022 12:00:00 AM"
distance: "25"
id: 0 <- here I want autoincrement ID
name: "Test ONE"
-My6qUykRSjuxu_MnyO_
date: "Feb 20, 2022 12:00:00 AM"
distance: "25"
id: 0 <- here I want autoincrement ID
name: "Test TWO"
I cannot put to field id my incremented id from above, which Firebase is adding, after putting Item to database.
I'm using api Firebase and my code looks like this :
Service:
#POST("${FirebaseFactory.BASE_URL}/Trips.json")
suspend fun saveTrip(#Body trip : Item) {
}
And ViewModel:
val testPutTrips = client.saveTrip(Item("Test ONE", "25", "Feb 20, 2022 12:00:00 AM", here i'm nothing passsing, because my Model has autoincrement, but it doesnt work and always put me 0))
Model:
#Entity(tableName = "trip")
data class Item(
#ColumnInfo(name = "name") val name: String,
#ColumnInfo(name = "distance") val distance: String,
#ColumnInfo(name = "date") val date: Date,
#PrimaryKey(autoGenerate = true) val id: Int = 0)
Is it possible to put incremented ID to filed?
From the Firebase documentation on appending data to a list:
You can use the reference to the new data returned by the push() method to get the value of the child's auto-generated key or set data for the child. Calling getKey() on a push() reference returns the value of the auto-generated key.
In code it'd look something like:
val newRef = mDatabase.child("Trips").push();
yourObject.id = newRef.key;
newRef.setValue(yourObject);

Luxon.js get the count of days in each month for a given date range

Is there is an efficient way to get a count of days grouped by month in a date range?
For example, given a date range of 2020-01-30 to 2020-02-03 the output would be { 'January': 2, 'February': 3 }.
I think there's no more efficient way other than calculating it.
const firstDateToPass = { year: 2020, month: 1, day: 26 };
const secondDateToPass = { year: 2020, month: 1, day: 29 };
const getCountOfDaysGroupedByMonth = (startDate, endDate) => {
const firstMonthDateTime = DateTime.fromObject(startDate);
const secondMonthDateTime = DateTime.fromObject(endDate);
if (firstMonthDateTime.month === secondMonthDateTime.month) {
// In same month
// Return difference in days
return {
[firstMonthDateTime.monthLong]: secondMonthDateTime.day - firstMonthDateTime.day
}
}
}
console.log(getCountOfDaysGroupedByMonth(firstDateToPass, secondDateToPass)) // { January: 3 }
You just need to cover the cases when it spans over multiple months, but I'll leave that figuring out to you for now?

Convert timezone specific date to locale using moment

I have the following data for a timezone:
{
"Id": "Pacific Standard Time",
"DisplayName": "(UTC-08:00) Pacific Time (US & Canada)",
"StandardName": "Pacific Standard Time",
"DaylightName": "Pacific Daylight Time",
"BaseUtcOffset": "-08:00:00",
"AdjustmentRules": [{
"DateStart": "0001-01-01T00:00:00Z",
"DateEnd": "2006-12-31T00:00:00Z",
"DaylightDelta": "01:00:00",
"DaylightTransitionStart": {
"TimeOfDay": "0001-01-01T02:00:00Z",
"Month": 4,
"Week": 1,
"Day": 1,
"DayOfWeek": 0,
"IsFixedDateRule": false
},
"DaylightTransitionEnd": {
"TimeOfDay": "0001-01-01T02:00:00Z",
"Month": 10,
"Week": 5,
"Day": 1,
"DayOfWeek": 0,
"IsFixedDateRule": false
},
"BaseUtcOffsetDelta": "00:00:00"
}, {
"DateStart": "2007-01-01T00:00:00Z",
"DateEnd": "9999-12-31T00:00:00Z",
"DaylightDelta": "01:00:00",
"DaylightTransitionStart": {
"TimeOfDay": "0001-01-01T02:00:00Z",
"Month": 3,
"Week": 2,
"Day": 1,
"DayOfWeek": 0,
"IsFixedDateRule": false
},
"DaylightTransitionEnd": {
"TimeOfDay": "0001-01-01T02:00:00Z",
"Month": 11,
"Week": 1,
"Day": 1,
"DayOfWeek": 0,
"IsFixedDateRule": false
},
"BaseUtcOffsetDelta": "00:00:00"
}],
"SupportsDaylightSavingTime": true
}
and the following date:
2019-01-05T07:30:07Z
Using moment, i'd like to convert this to my current locale which is
en-GB
How do i go about doing this with momentjs?
the problem seems to be that the date format i have is not compatible with moment.
I've prepared a jsfiddle with variables that i have access to:
http://jsfiddle.net/jimmyt1988/xe7ha5ms/1/
Your input is in ISO 8601 format recognized by moment. You can parse it using moment.tz:
The moment.tz constructor takes all the same arguments as the moment constructor, but uses the last argument as a time zone identifier.
then you can convert it to desired timezone using tz():
The moment#tz mutator will change the time zone and update the offset.
You can set locale on a moment object using locale() and then use format() to display value.
Here a code sample:
console.log(
moment.tz('2019-01-05T07:30:07', 'America/Los_Angeles') // parse input in given tz
.tz('Europe/London') // Convert moment to desired zone
.locale('en-gb') // set en-gb locale
.format('LLLL') // display result
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment-with-locales.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.23/moment-timezone-with-data-2012-2022.min.js"></script>
Figured it out, by using the utcOffset method:
http://jsfiddle.net/jimmyt1988/xe7ha5ms/2/
moment("2019-01-05T07:30:07Z")
.utcOffset("-08:00:00")
.format("DD/MM/YYYY HH:mm:ss");

Minimum tick interval (monthly) not working for datetime Highchart graph

I am working with date-time highchart and I want x-axis tick interval to appear every month(jan-12, Feb-12, Mar-12). But If the data points are less than 4 then the x-axis label starts showing days of month as well (10 dec,24 dec, 7 jan). How do I make sure that even if there are less data points or the graph is zoomed, the tick interval are monthly. Here is the code for x-axis:
xAxis : {
type: 'datetime',
tickmarkPlacement:'on',
dateTimeLabelFormats: {
month: '%b-%y',
},
minRange:1*30*24*60*60*1000,
labels : {
rotation :'280',
align:'right',
style: {
fontFamily : 'Helvetica',
fontSize: '10px'
}
}
}
Thanks in Advance
As mentioned in my earlier comment, the easiest way to get what you've asked for is to set the tickInterval:
xAxis: {
type: 'datetime',
tickInterval:86400000 * 30
}
Example:
http://jsfiddle.net/jlbriggs/Lmfa5v55/
With this setup it doesn't matter what interval your data is in - in the example, it's daily - or if it's irregularly spaced or not.
It doesn't matter what level of zoom, or how many data points, you'll have a tick and label for each month within the bounds of the data.
Try put exact interval tick, and automatic day or month will appear.
You only need format label, after put ticks.
Options.xAxis.tickPositioner = function () {
const ticks = this.series[0].xData;
let result = [];
for (let index = 0; index < ticks.length; index++) {
result.push(ticks[index]);
}
return result;
};
and format xAxis
labels: {
format: "{value:%b-%Y}",
align: "center"
}
to tooltips
tooltip: {
valueSuffix: "",
valuePrefix: "",
xDateFormat: "%B - %Y",
valueDecimals: 0
},
The problem here is that not all the months have 30 days, is better not to set the tickInterval or the minRange. You could try to generate the months at your own, like:
startDate = Date.UTC(2012, 1, 1); //your starting date
// Set the xaxis value as first day of month
for (var i = 0; i < yourData.length; i++) {
var d = new Date();
d.setTime(startDate);
d.setMonth(d.getMonth() + i);
categories.push(d.getTime());
}
Or generate your own categories as shown on Highcharts demo page:
xAxis: {
categories: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec' //etc.
],
},
See a working demo of first option at: http://jsfiddle.net/gjkde5np/1/
Extracted from: How to set PointIntervals per month in HighChart
You could also check the code from highcharts "Time series with irregular intervals" http://www.highcharts.com/demo/spline-irregular-time . Here they use the [Date.UTC(1970, 9, 21), 0], [Date.UTC(1970, 10, 4), 0.28]

How to make fullcalendar to get current month events only?

I am using fullcalendar plugin to get and display holidays of a month via Ajax. The problem I am having, is that the method that retrieves the holidays accepts only a year and a month as parameter, not a date range.
When using month view of fullcalendar, the start and end parameter ranges from feb 23rd and Apr 6th. I need it to range from Mar 1st to Mar 31st. That way, I can only get year and month part to call the method.
This is what I tried but without success:
$('#calendar').fullCalendar({
monthNames: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
monthNamesShort: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
dayNames: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
dayNamesShort: ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'],
events: '/get_month_holidays',
start: {
month: new Date((new Date()).getFullYear(), (new Date()).getMonth(), 1)
},
end: {
month: (new Date((new Date()).getFullYear(), (new Date()).getMonth() + 1, 1)) - 1
},
buttonText: {
today: 'hoy'
}
})
Any help will be appreciated,
Thanks
Jaime
Finally I used:
eventSources: [
{
url: '/get_month_holidays',
type: 'POST',
data: function() {
var fecha = $('#calendar').fullCalendar('getDate');
return {
month: fecha.getMonth() + 1,
year: fecha.getFullYear()
}
}
}
],
And it worked. Thanks anyway.
Jaime
jstuardo's solution adds new parameters to the request so you end up with something like this:
http://your.api.com/events?month=8&year=2015&start=2015-07-27&end=2015-09-07
Which is quite confusing and requires you to change the API accordingly.
Better solution would be to change the default start and end parameters. You can achieve that using something like this:
{
url: baseUrl + '/events',
startParam: null, //resetting default fullcalendar parameter
endParam: null, //resetting default fullcalendar parameter
data: function() {
var date = $('#gc-calendar').fullCalendar('getDate')._d;
var firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
var lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0);
firstDay = $filter('date')(firstDay, 'yyyy-MM-dd');
lastDay = $filter('date')(lastDay, 'yyyy-MM-dd');
//AngularJS way of changing the date format to yyyy-mm-dd
return {
start: firstDay,
end: lastDay
}
}
}
This way your request looks like this:
http://your.api.com/calendar_orders?start=2015-08-01&end=2015-08-31
You can format the date to 'yyy-MM-dd' using any method you like. You can find a bunch of them here:
Get String in YYYYMMDD format from JS date object?

Resources