What is the preferred way of working with dates and JavaScript? - faunadb

When working with a Faunadb record that contains a date value, I struggled with using that date in JavaScript. Eventually I got it working like so:
project.shipDate = new Date(await client.query(q.Format('%t', project.shipDate)));
This seems fine, but I also noticed I could do this:
let test = JSON.parse(JSON.stringify(project.created));
console.log(test);
datetest = new Date(test["#date"]);
Which seems wonky (grin), but may be quicker as it's not using the Fauna client library. Which should I prefer?

The JS driver has several helper classes that let you cast the javascript Time and Date objects to their FQL counterparts.
Here is an example.
From Fauna to JS
You can create a new document that contains a date value.
const project = await client.query(
q.Create(
q.Collection("projects"),
{ data: { shipDate: q.ToDate(q.Now()) } }
)
)
You can retrieve the date value and use as a javascript Date object by using the value property
const shipDate = new Date(project.data.shipDate.value)
From JS to Fauna
The date value can be modified however you want, and you can pass it back to FQL using the values.FaunaDate class.
const { values } = require('faunadb')
/* ... */
let nextDay = new Date(shipDate.getTime() + 86400000)
const faunaDate = new values.FaunaDate(nextDay)
Full Example
const project = await client.query(
q.Create(
q.Collection("projects"),
{ data: { shipDate: q.ToDate(q.Now()) } }
)
)
console.log(project)
const shipDate = new Date(project.data.shipDate.value)
console.log(shipDate)
let nextDay = new Date(shipDate.getTime() + 86400000)
console.log(nextDay)
const projectRef = project.ref
const projectUpdate = await client.query(
q.Update(
projectRef,
{ data: { shipDate: new values.FaunaDate(nextDay) } }
)
)
console.log(projectUpdate)
{
ref: Ref(Collection("projects"), "307924674409398337"),
ts: 1629918703380000,
data: { shipDate: Date("2021-08-25") }
}
2021-08-25T00:00:00.000Z
2021-08-26T00:00:00.000Z
{
ref: Ref(Collection("projects"), "307924674409398337"),
ts: 1629918703470000,
data: { shipDate: Date("2021-08-26") }
}

Related

Azure IoT Hub sql query

I am trying to query the IoT hub devices twins using query language. I have the following code snippet which is not working.I am not getting any results. When i replace dt with some hard coded date then i will get the device list. Is it like I cant pass a variable using this queries to hub? please help me.
var dt = new Date();
dt.setDate( dt.getDate() - 4 );
console.log(dt);
var query = registry.createQuery('SELECT * FROM devices where lastActivityTime > dt', 100);
var onResults = function(err, results) {
if (err) {
console.error('Failed to fetch the results: ' + err.message);
} else {
// Do something with the results
results.forEach(function(twin) {
console.log(twin.deviceId);
});
if (query.hasMoreResults) {
query.nextAsTwin(onResults);
}
}
};
You can achieve what you want by using a JavaScript template string - note the use of ` and ' in the example:
var dt = new Date();
dt.setDate( dt.getDate() - 3);
var dateString = dt.toISOString();
var query = registry.createQuery(`SELECT * FROM devices WHERE lastActivityTime > '${dateString}'`, 100);

React Native: how can I achieve the dynamic keys with multiple objects

Here is my code I tried,
var array=[];
var list = this.state.list;
var getList = function(i){
var add = +i + 1;
return {
["value"+add]:{
Description:list[i].Description,
Length:list[i].Length,
Height:list[i].Height,
Weight:list[i].Weight,
VolumeWeight:list[i].VolumeWeight,
ActualWeight:list[i].ActualWeight,
}
}
}.bind(this)
for(var i in list){
array.push(getList(i));
}
var dataArray = array.map(function(e){
return JSON.stringify(e);
});
dataString = dataArray.join(",");
data1 = {
ConsigneeBranchName:this.state.searchText,
ConsigneeBranchCode:this.state.code,
ConsigneeBranchFullAddress:this.state.DAddress,
SenderBranchCode:this.state.code1,
SenderBranchName:this.state.searchTexts,
SenderBranchFullAddress:this.state.Address,
CreatedByEmployeeCode:id,
CreatedByEmployeeFullName:userName,
jsonString:{
JsonValues:{
id:"MyID",
values:dataString
}
}
}
But I want the result is exactly this
var result = {
"ConsigneeBranchName":"",
"ConsigneeBranchCode":"",
"ConsigneeBranchFullAddress":"",
"SenderBranchCode":"",
"SenderBranchName":"",
"SenderBranchFullAddress":"",
"CreatedByEmployeeCode":"",
"CreatedByEmployeeFullName":"",
"jsonString":"{
"JsonValues": {
"id": "MyID",
"values": {
"value1":{
"Description”:"testSmarter1",
"Length”:"60",
"Height”:"50",
"Weight”:"70",
"VolumeWeight”:"75",
"ActualWeight”:”78"
},
"value2:{
"Description":"Documents",
"Length":"120",
"Height":"68",
"Weight":"75",
"VolumeWeight":"122.4",
"ActualWeight":"123"
},
}
}
}
};
Please any one help me
I want the object with dynamic keys within a single object {key1:{des:1,value:as},key2:{des:2,value:aw},key3:{des:3,value:au}}
can you please help me I have tried so many times
see this below image I want this part, inside the single object, I can join multiple objects with dynamic keys
lodash already has a function called keyBy, you can use it to get this functionality. If adding lodash doesn't make sense in your project.
I have implemented a vanilla JS version.
function keyBy(array, mapperFn) {
const resultObj = {};
array.map(item => resultObj[mapperFn(item)] = item);
return resultObj;
}
function arrayToObject (array, keyName = 'id') {
return keyBy(array, function(element) {return element[keyName]});
}
API:
arrayToObject(targetArray, stringNameOfThePorpertyYouWantToUseAsKey);
USAGE:
const listOfUsers = [{name: 'Jenitha', reputation: 6}, {name: 'Chandan', reputation: 3}];
const mapOfUsersByName = arrayToObject(listOfUsers, 'name');

How I can set expiration date for AsyncStorage - react native

I am using react native async storage it works good but in some cases, I have to set an expiration date for data and refresh my storage I checked
AsyncStorage documentation but there are no options to set expire after a specific time.
only available options are:-
AsyncStorage.removeItem
AsyncStorage really only handles storage and nothing beyond that.
If you want to set an expiration, just put a key in your data for access date and set it to new Date(). Then, when you pull data, do a date check on the expiration key based on when it should expire.
first, I am storing objects, not strings so my solution will be based on object case if anyone uses strings he can append expireAt the object key then he will extract expire date and compare it with the current date
my solution:-
/**
*
* #param urlAsKey
* #param expireInMinutes
* #returns {Promise.<*>}
*/
async getCachedUrlContent(urlAsKey, expireInMinutes = 60) {
let data = null;
await AsyncStorage.getItem(urlAsKey, async (err, value) => {
data = (JSON.parse(value));
// there is data in cache && cache is expired
if (data !== null && data['expireAt'] &&
new Date(data.expireAt) < (new Date())) {
//clear cache
AsyncStorage.removeItem(urlAsKey);
//update res to be null
data = null;
} else {
console.log('read data from cache ');
}
});
//update cache + set expire at date
if (data === null) {
console.log('cache new Date ');
//fetch data
data = fetch(urlAsKey).then((response) => response.json())
.then(apiRes => {
//set expire at
apiRes.expireAt = this.getExpireDate(expireInMinutes);
//stringify object
const objectToStore = JSON.stringify(apiRes);
//store object
AsyncStorage.setItem(urlAsKey, objectToStore);
console.log(apiRes.expireAt);
return apiRes;
});
}
return data;
},
/**
*
* #param expireInMinutes
* #returns {Date}
*/
getExpireDate(expireInMinutes) {
const now = new Date();
let expireTime = new Date(now);
expireTime.setMinutes(now.getMinutes() + expireInMinutes);
return expireTime;
}
You can use this also, improvement from Ahmed Farag Mostafa answers
import AsyncStorage from "#react-native-async-storage/async-storage";
export default class ExpireStorage {
static async getItem(key) {
let data = await AsyncStorage.getItem(key);
data = JSON.parse(data);
if (
data !== null &&
data.expireAt &&
new Date(data.expireAt) < new Date()
) {
await AsyncStorage.removeItem(key);
data = null;
}
return data?.value;
}
static async setItem(key, value, expireInMinutes) {
const data = { value };
if (expireInMinutes) {
const expireAt = this.getExpireDate(expireInMinutes);
data.expireAt = expireAt;
} else {
const expireAt = JSON.parse(await AsyncStorage.getItem(key))?.expireAt;
if (expireAt) {
data.expireAt = expireAt;
} else {
return;
}
}
const objectToStore = JSON.stringify(data);
return AsyncStorage.setItem(key, objectToStore);
}
static async removeItem(key) {
return AsyncStorage.removeItem(key);
}
static getExpireDate(expireInMinutes) {
const now = new Date();
const expireTime = new Date(now);
expireTime.setMinutes(now.getMinutes() + expireInMinutes);
return expireTime;
}
}

dojo 1.8: populate select box with items from database including null values

Hi I just want to populate the select or comboBox.
I am able to populate both with the searchAttr to any string from JSON. But not so when there are null values.
JSON string :
[{"batch":"0000001000"},{"batch":"0000"},{"batch":""},{"batch":null}]
dojo code:
var selBatch = new ComboBox //located at the left side of the page and it is the second select box in a row
(
{ id:'ID_selBatch',
value:'',
searchAttr:'batch',
placeHolder:'Select...',
style:{width:'150px'},
}, 'node_selBatch'
);
on(selTest, 'change', function(valueCard)
{
var selectedTest = this.get('displayedValue');
var selBatch = registry.byId('ID_selBatch');
console.debug('Connecting to gatherbatches.php ...');
request.post('gatherbatches.php',
{ data:{nameDB:registry.byId('ID_selPCBA').value, nameCard : valueCard},
handleAs: "json"}).then
(
function(response)
{
var memoStore2 = new Memory({data:response});
selBatch.set('store', memoStore2);
selBatch.set('value','');
console.debug('List of batches per Test is completed! Good OK! ');
},
function(error)
{
alert("Batch's Error:"+error);
console.debug('Problem: Listing batches per Test in select Test is BAD!');
}
);
selBatch.startup();
});
Error :
TypeError: _32[this.searchAttr] is null
defer() -> _WidgetBase.js (line 331)
_3() -> dojo.js (line 15)
_f.hitch(this,fcn)(); -> _WidgetBase.js (line 331)
Please advise though it might strange to have null values populate in the select box but these null values are related to data in other columns in database, so the null values included so that I can apply mysql scripts later. Or do you have other better suggestion?
Clement
You can create a QueryFilter as in this jsfiddle to achieve what you want, but it might be simpler to have two data items. Your original model with possibly null batch properties, and the model you pass to the store which is used by the ComboBox.
But anyway, this can work:
function createQueryFilter(originalQuery, filter) {
return function () {
var originalResults = originalQuery.apply(this, arguments);
var results = originalResults.filter(filter);
return QueryResults(results);
};
}
and
var memoStore = new Memory({
data: data
});
memoStore.query = createQueryFilter(memoStore.query, function (item) {
console.log(item);
return !!item.batch;
});
and the dummy data:
function createData1() {
var data = [];
for (var i = 0; i < 10; i++) {
data.push({
name: "" + i,
batch: (0 === i % 2) ? "batch" + i : null
});
}
return data;
}
Screenshot. The odd numbered batch items are null in my example.

Dojo's dijit.calendar and isDisabledDate

I'd like to use the dijit.calendar widget, but be able to set disabled dates from an array of dates. All the examples point out how to disable weekends, but I need to disable special dates too.
Can anyone point me in the right direction to utilize a custom function in the isDisabledDate, rather than just whats in dojo.date.locale?
I've tried writing a function, and putting it inside the isDisabledDate attribute, but all I get is errors.
I'm making a huge assumption here, that you're populating your array for each month displayed via an XHR request. This XHR request returns an array of strings in Y-m-d format (i.e. ['2011-11-29','2011-11-30']). Another slight assumption is that the XHR request returns an array of dates that should be enabled, but this can be reversed by swapping the disable = true; and disable = false; lines
I don't know how much detail to go into without being patronizing, so if anything is unclear I'll try to clarify afterwards.
dojo.provide("custom.Calendar");
dojo.declare("custom.Calendar", dijit.Calendar, {
_xhr: null,
// Month/Year navigation buttons clicked
_adjustDisplay: function(){
// Ensure all dates are initially enabled (prevents seepage)
this.isDisabledDate = function(date) {
return false;
};
this.inherited(arguments);
this._disableAndPopulate();
},
constructor: function(){
this.inherited(arguments);
this._disableAndPopulate();
},
// Month drop down box
_onMonthSelect: function(){
// Ensure all dates are initially enabled (prevents seepage)
this.isDisabledDate = function(date) {
return false;
};
this.inherited(arguments);
this._disableAndPopulate();
},
// Set disabled dates and re-render calendar
_disableAndPopulate: function(){
var currDate = this.currentFocus;
// Get Lower bound date
var startDate = new Date();
startDate.setFullYear(currDate.getFullYear(), currDate.getMonth(), -5);
// Create ymd dates manually (10x faster than dojo.date.locale.format)
var startMonth = (startDate.getMonth()<9 ? '0' + (startDate.getMonth()+1) : startDate.getMonth()+1);
var startDay = (startDate.getDate()<10 ? '0' + startDate.getDate() : startDate.getDate());
var ymdStartDate = startDate.getFullYear() + '-' + startMonth + '-' + startDay;
// Get Upper bound date
var endDate = new Date();
endDate.setFullYear(currDate.getFullYear(), currDate.getMonth() + 1, 14);
// Create ymd dates manually (10x faster than dojo.date.locale.format)
var endMonth = (endDate.getMonth()<9 ? '0' + (endDate.getMonth()+1) : endDate.getMonth()+1);
var endDay = (endDate.getDate()<10 ? '0' + endDate.getDate() : endDate.getDate());
var ymdEndDate = endDate.getFullYear() + '-' + endMonth + '-' + endDay;
var calendar = this;
// Get IssueDates
var issueDates;
// If an existing xhr request is still running, cancel it before starting a new one
if (this._xhr) {
this._xhr.cancel();
}
this._xhr = dojo.xhrGet({
url: "http://.....", // url of server-side script
content: {
startDate: ymdStartDate, // Earliest possible date displayed on current month
endDate: ymdEndDate, // Last possible date displayed on current month
filters: {} // Any additional criteria which your server-side script uses to determine which dates to return
},
failOk: true, // Prevent error being logged to console when previous XHR calls are cancelled
load: function(data){
issueDates = dojo.fromJson(data);
if (issueDates === undefined) {
// Error with xhr
} else {
calendar.isDisabledDate = function(date) {
var disable = true;
// Create ymdDate manually (10x faster than dojo.date.locale.format)
var month = (date.getMonth()<9 ? '0' + (date.getMonth()+1) : date.getMonth()+1);
var day = (date.getDate()<10 ? '0' + date.getDate() : date.getDate());
var ymdDate = date.getFullYear() + '-' + month + '-' + day;
// Loop through array returned from XHR request, if it contains current date then
// current date should not be disabled
for (key in issueDates) {
if (issueDates[key] == ymdDate) {
disable = false;
break;
}
}
return disable;
};
calendar._populateGrid(); // Refresh calendar display
}
},
// Log any errors to console (except when XHR request is cancelled)
error: function(args) {
if (args.dojoType == 'cancel') {
// Request cancelled
} else {
console.error(args);
}
}
});
},
onClose: function() {
// If an existing xhr request is still running, cancel it before starting a new one
if (this._xhr) {
this._xhr.cancel();
}
}
});
AMD style:
CalendarLite.js.uncompressed.js in dojo 1.7.1 contains the isDisabledDate function:
isDisabledDate: function(/*===== dateObject, locale =====*/){
// summary:
// May be overridden to disable certain dates in the calendar e.g. `isDisabledDate=dojo.date.locale.isWeekend`
// dateObject: Date
// locale: String?
// tags:
// extension
/*=====
return false; // Boolean
=====*/
},
...
You could re-implement the function using this example:
var myCalendar = declare(Calendar, {
datesToDisable : [],
constructor: function(args) {
this.inherited("constructor", arguments);
this.datesToDisable = args.datesToDisable;
},
isDisabledDate: function(/*Date*/date, /*String?*/locale){
return array.some(this.datesToDisable, function(item) {
return dojo.compare(item, date, "date") === 0;
});
}
});
Then you can use the following constructor and datesToDisable parameter to specify your array.
var someCalendar = new myCalendar({datesToDisable: [new Date(...),....,new Date(....)]},...);
or try this for a fast and dirty solution:
var someCalendar = new Calendar(...);
someCalendar.datesToDisable = [new Date(...),....,new Date(....)];
someCalendar.isDisabledDate = function(/*Date*/date, /*String?*/locale){
return array.some(this.datesToDisable, function(item) {
return date.compare(item, date, "date") === 0;
});
}
But I would recommend the first approach. The assumption is that you know AMD style in order to "import" dijit/Calendar, dojo/_base/array and dojo/date (for "date.compare()" to work).
Cheers!
You can add list of holidays in an array with its timestamp and use indexOf method to find matching dates while populating the calendar in the overriding function of isDisabledDate
var holidays = new Array();
var holidDt = new Date("October 2, 2012");
holidays.push(holidDt.getTime());
Now access the holiday array and check its presence. If present disable, else enable by overriding the isDisabledDate function
isDisabledDate: function(d) {
var dt = new Date(d);
var dayN = dt.getDay();
dt.setHours(0, 0, 0, 0);
/**
* Condition for
* 1. Weekends
* 2. Holidays (holiday array needs to be updated with holiday times)
*/
return ((!((dayN > 0) && (dayN < 6))) || (arrayUtil.indexOf(holidays, dt.getTime()) >= 0));
}