In firebase realtime database, something seemingly basic does not work.
Here is the JS code:
let myDBRef = firebase.database().ref('MyCollection');
newItem = myDBRef.push(),
startTime = firebase.database.ServerValue.TIMESTAMP,
endTime = startTime + 24*3600*1000
newItem.set({
someField:'myFieldValue',
startTime:startTime,
endTime:endTime
});
I expect something like the following in the DB as a result:
-MXb9s2-3mX3XZL_azRv
endTime: 1601691254295
someField: "myFieldValue"
startTime: 1601604854295
But I get this instead:
-MXb9s2-3mX3XZL_azRv
endTime: "[object Object]86400000"
someField: "myFieldValue"
startTime: 1601604854295
What am I doing wrong and how do I need to change the JS code to get the result I expect?
The firebase.database.ServerValue.TIMESTAMP is not the current server-side timestamp, but a marker value that gets translated to the actual server-side timestamp when written to the database.
That means that you can't store calculated values like you do now in a single step. You have two options:
Store the duration instead of the endTime. So:
let myDBRef = firebase.database().ref('MyCollection');
newItem = myDBRef.push(),
startTime = firebase.database.ServerValue.TIMESTAMP,
duration = 24*3600*1000
newItem.set({
someField:'myFieldValue',
startTime:startTime,
duration:duration
});
Store the startTime first, and then calculate the endTime either in the client or in a Cloud Function, that then updates the database. This'd be something like:
let myDBRef = firebase.database().ref('MyCollection');
newItem = myDBRef.push(),
startTime = firebase.database.ServerValue.TIMESTAMP,
duration = 24*3600*1000
newItem.set({
someField:'myFieldValue',
startTime:startTime,
}).then(() => {
newItem.child("startTime").once("value").then((snapshot) => {
newItem.update({ endTime: snapshot.val() + duration });
})
})
Related
I am having big difficulties in getting this done so I have to ask you guys for help now.
I am hitting the binance API endpoint for historical futurerates and I need all available data for every symbol in my array (from current to the very first created item).
The API offers query parameters and limits to do so "startTime" and "endTime" of type long timestamp in ms.
Here is the link to the docs
[fundingrate api endpoint[1]
[1]: https://binance-docs.github.io/apidocs/futures/en/#get-funding-rate-history
Using my approach, I am getting a bunch of results, but they randomly stop at some point in the past, so my pagination logic must be wrong. I just can not seem to find out where.
This is my current code
(async () => {
try {
const markets = symbols;
const targetDate = moment("2018-01-01"); //just one random past date I know it is for sure before any future contract creation on binance
for (let i = 0; i < markets.length; i++) {
let fundingRates = [];
symbol = markets[i];
let startTime, endTime, days_per_batch;
const initialResult = await binance.futuresFundingRate(symbol, { //make a request without a range to get a start and endpoint for pagination
limit: 1000,
});
startTime = moment(initialResult[0].fundingTime); //use the first retrieved item as startTime
endTime = moment(initialResult[initialResult.length - 1].fundingTime); //use last received item as endTime
days_per_batch = endTime.diff(startTime, "days"); //difference in days between first and last retrieved item of initial request
while (endTime.isAfter(targetDate)) {
const result = await binance.futuresFundingRate(symbol, {
startTime: startTime.unix(), //cast to timestamps
endTIme: endTime.unix(), //cast to timestamps
limit: 1000,
});
//concat retrieved result with result array that gets exported to csv
fundingRates = [].concat(
...result.map((e) => {
return {
symbol: e.symbol,
fundingRate: e.fundingRate,
fundingTime: moment(e.fundingTime),
};
})
);
//set the endTime to the previosu startTime and the startTime to startTime - days per batch (difference in days between first item and last item of result)
endTime = startTime;
startTime.subtract(days_per_batch, "days");
}
exportToCSV(symbol, fundingRates);
console.log("processing " + i + " / " + markets.length)
}
} catch (error) {
console.log(error);
}
})();
I am trying to convert JSON time string to local time as below
angular.forEach($scope.calendarData, function(item) {
item.scheduleArray.startTime = new Date(item.scheduleArray.startTime);
item.scheduleArray.endTime = new Date(item.scheduleArray.endTime);
});
For example
startTime = "1970-01-01T08:52:00.000Z"
But when I execute the code, it says Invalid date. How can I solve this problem
let scheduleArray = {alert: "emailNotification", endTime: "1970-01-01T08:52:00.000Z", expanded: true, startTime: "1970-01-01T11:12:00.000Z", title: "New Schedule"};
let calendarData = [];
calendarData.push({'scheduleArray':scheduleArray});
angular.forEach(calendarData, function(item) {
item.scheduleArray.startTime = new Date(item.scheduleArray.startTime);
item.scheduleArray.endTime = new Date(item.scheduleArray.endTime);
console.log(item.scheduleArray.startTime);
});
console.log(calendarData);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.min.js"></script>
I want to recreate whatsapp/telegram-like timeline where messages divided by days.
For rendering messages in React I use Object.key(messages).map function.
Object.keys(this.messages).map(e => {
return <div key={i++}>
{ this.messages[e] }
How to add e.g. 'today' between the last yesterday and first today messages?
I would group all messages into separate arrays, each for each day that occurs. In order to do that, create an object - its keys will be unique days and its values - messages from these days.
// object similar to your 'messages' state
const messages = {
message1: {
body: "one day before message",
time: 1534433188201
},
message2: {
body: "newest message",
time: 1534519588201
},
message3: {
body: "2 days before newest message",
time: 1534346788201
},
message4: {
body: "also 2 days before newest message",
time: 1534346788250
}
};
// creating array from your object
const messagesArray = Object.keys(messages).map(m => messages[m]);
// sorting array - oldest to newest
const latestMessages = messagesArray.sort((a, b) => a.time > b.time);
// grouping by date - create an object, each key is a different date and value is an array of messages from that day
const groupedByDate = {};
latestMessages.forEach(message => {
const date = new Date(message.time);
const day = date.getDate();
const month = date.getMonth();
const year = date.getFullYear();
// this will create 'date_17-7-2018' format as an example - you can do whatever you want/need here
const key = `date_${day}-${month}-${year}`;
// push message to existing key or create new array containing this message
if(groupedByDate[key]) {
groupedByDate[key].push(message);
} else {
groupedByDate[key] = [message];
}
});
console.log(groupedByDate);
The rendering part seems easy now - here's an example how i would approach this:
Map over Object.keys(groupedByDate) and for each key return div or span with a className="date-label"(example). If a day extracted from this key is equal to (new Date()).getDate() - render "today", if it's (new Date()).getDate() - 1 - render "yesterday", otherwise render "X days ago". Now inside this map loop you also need to map over groupedByDate[key] (array of messages from this day) and render messages.
Object.keys(this.messages).map(message => {
const date = new Date();
date.setHours(0,0,0,0); // will set to midnight
const today = Math.round(date.getTime() / 1000);
const timeDifference = this.state.time - today;
const isInRange = timeDifference >= 0 && timeDifference <=86400;
if (isInRange && !this.state.labelAlreadyPresent) {
this.setState({ showLabel: true, labelAlreadyPresent: true });
} else if(!isInRange) {
this.setState({ labelAlreadyPresent: false, showLabel: true });
} else {
this.setState({ showLabel: false });
}
return (
<div key={message.time}>
{this.state.showLabel && <label> Today </label>}
{ message.body }
</div>
);
so basically you first get today's date and set it to midnight. then you get the unix timestamp in seconds. After that you compare the timestamp with the timestamp you received in response and if its within the range of 0 to 86400(equal to 1 day) then you show the Today label.
In the initial state make labelAlreadyPresent and showLabel as false
I'm new to firebase, actually I'm trying to load some data based on timestamp and retrieve between two timestamp using startat and endat. Data is pushed through Python.
The data is as shown in the sample screenshot
sample data
The data path popping-fire-7751.firebaseio.com/device488
activevolt: 396
avgPowerFactor: 0.95
avgThdi: 7.5
cubetemp: 37
datetime: "2016-02-08 15:16:32"
timestamp: 1454924792
totalPowerGen: 34
I'm pushing data through python setting the priority as timestamp.
When I try to filter as shown here it returns null. But without startAt and endAt it shows all the values.
http://jsfiddle.net/casperkamal/EZUtP/64/
var startTime = 1454924792;
var endTime = 1454924798;
new Firebase("https://popping-fire-7751.firebaseio.com/")
.startAt(startTime)
.endAt(endTime)
.once('value', show);
can anybody help me on what I'm doing wrong ?
You're trying to skip a level in your JSON tree:
var startTime = 1454924792;
var endTime = 1454924798;
new Firebase("https://popping-fire-7751.firebaseio.com/")
.child('device488')
.startAt(startTime)
.endAt(endTime)
.once('value', show);
I highly recommend that you don't depend on the implicit priority anymore and instead just filter using orderByChild()
new Firebase("https://popping-fire-7751.firebaseio.com/")
.child('device488')
.orderByChild('timestamp')
.startAt(startTime)
.endAt(endTime)
.once('value', show);
You'll need to add an index to your Security Rules:
{
"rules": {
"device488": {
".indexOn": ["timestamp"]
}
}
}
But the more explicit behavior is well worth the effort of adding this.
I am using html5 local storage to store date as following:
var object = {value: "value", timestamp: new Date().getTime()}
localStorage.setItem("key", JSON.stringify(object));
var object = JSON.parse(localStorage.getItem("key")),
dateString = object.timestamp,
now = new Date().getTime().toString();
compareTime(dateString, now);
alert(datestring - now); //tried this but it always alerts 0.
Now I want to know how to make a function that can check if time stored in localstorage is already past 12 hour.
You will know your code was correct, if you use timeout for get now.
var object = {value: "value", timestamp: new Date().getTime()}
localStorage.setItem("key", JSON.stringify(object));
var object = JSON.parse(localStorage.getItem("key")),
dateString = object.timestamp;
setTimeout(function() {
var now = new Date().getTime().toString();
alert(dateString - now);
}, 1000);