Unable to get new values from external module - javascript

I have a date module that returns current date that is set in system:
function getDateFormatAndISODate() {
const dates = require('./resources/getSystemDate').getSystemDate();
return dates;
}
module.exports.getDateFormatAndISODate = getDateFormatAndISODate;
I am requiring it in another file:
import * as isoDateModule from './datastream-get-iso-module';
The issue is the method call is not returning new date values when user changes the date manually from system and call this method again:
isoDateModule.getDateFormatAndISODate(dateVal);
I am using c node addon in my project and I am requiring it like this:
function requireUncached(module) {
delete require.cache[require.resolve(module)];
return require(module);
}
const dates = requireUncached('./resources/getSystemDate').getSystemDate();
But still I get the old date values. Not sure whats missing

Related

Javascript macOS Error: Named parameters must be passed as an object

I'm trying to implement automation for the task manager Things 3 on macOS using JXA (Javascript for macOS automation) and I'm running it to a strange error. I have spent countless hours trying to fix this myself and with the help of others. I am trying to use the following method described in the documentation:
As following:
// Set TaskApp as the app to use
var TaskApp = Application('Things3');
// Get the ToDo from toDos
var task = TaskApp.toDos["test555342343"]
// Get today as a date
var today = new Date()
// Schedule the task for Today
task.schedule(task.id(), {for: today})
This returns the error:
Error: Error: Named parameters must be passed as an object.
When using another method (like show) the specefier works as expected:
Example:
// Set TaskApp as the app to use
var TaskApp = Application('Things3');
// Get the ToDo from toDos
var task = TaskApp.toDos["test555342343"]
// Bring Things3 to the Forground
TaskApp.activate()
// Show the task
task.show(task.id())
Will show the selected todo. Creating a task with with a deadline set to the date object also produces the correct result (a task with the deadline of date).
This documentation can only be found when you have things3 installed on macOS and you reference the Script Library. I have added the documentation as PDF. The described error also apply's to the move method. Instead of parsing a date you parse a List Object to it which will resolve in the same error.
Link to documentation PDF → Link
The Things documentation is wrong: schedule is a method of Application, not of ToDo, which is why it asks for a todo specifier (it wouldn’t need that one if it was a property of a ToDo object already). The working code hence is:
// Set TaskApp as the app to use
var TaskApp = Application('Things3')
// Get the ToDo from toDos
var task = TaskApp.toDos["test555342343"]
// Get today as a date
var today = new Date()
// Schedule the task for Today
TaskApp.schedule(task, {for: today})
Note that task already is a ToDo specifier; you don’t need the detour through task.id(), which converts the ToDo specifier into an ID String before letting the schedule method cast that back to a specifier.

How to customise the "invalid date" in moment

Im trying to customise the error message of moment when a date is invalid, so I don't get "Invalid Date" each time.
For exemple one time I would like the result to be blank if the date is not correct, an other time I want it to be "This date is not correct"
Is there any way to do so ?
I searched everywhere and didn't find anything, so far the only way is to change it that way
moment.updateLocale("es", {
invalidDate: "Fecha invalida"
});
But it's just to change the message everywhere. I want to be able to custom it everywhere.
So the only solution I found so far is to use the function
isValid();
And so create a function like
CustomMomentErrorMsg(moment(...), 'my error msg')
and the function can look like this
function CustomMomentErrorMsg(MyDate, errorMessage) {
if (MyDate.IsValid()) {
return MyDate
}
else {
return errorMessage
}
}
or something like
function CustomMomentErrorMsg(MyDate, errorMessage) {
if (MyDate == "Invalid Date") {
return errorMessage }
else {
return MyDate
}
}
Isnt there a way just like
moment(MyDate).format("DD/MM/YYYY").error("This is a custom error message")
Thanks
If you look at moment's source code, you'll see that the error message for an invalid date is part of the locale configuration, and the format() function internally calls the formatMoment() function, which, in turn, checks for validity and returns the global locale configuration for the error message text:
function formatMoment(m, format) {
if (!m.isValid()) {
return m.localeData().invalidDate();
}
// the rest of the code doesn't interest us in your case
}
( those functions can be understood as getters for internal properties ._locale and ._invalidDate which can, but absolutely should not be accessed by the end user as it's considered bad practice - this is why there is this public API available ).
Default (parent) locale configuration is stored in the baseConfig variable:
var baseConfig = {
calendar: defaultCalendar,
longDateFormat: defaultLongDateFormat,
invalidDate: defaultInvalidDate,
...
...
...
meridiemParse: defaultLocaleMeridiemParse,
};
and the default value is set a few lines above like this:
var defaultInvalidDate = 'Invalid date';
As you can see, the error text is not a property of the moment, it's a property of the locale and so can't be different for different moment objects. Unless you're willing to change the locale settings every time you generate a new date, the solution that you provided seems legit and usable!
P.S. I put some related console.log() in this code snippet
// creating an invalid moment
var m = moment.invalid();
// don't use properties that begin with underscore!
console.log(m._isValid);
console.log(m.isValid());
// formatting returns the same result as toString()
// and the general message in the locale data object
console.log(m.format());
console.log(m.toString());
console.log(m.localeData()["_invalidDate"]);
console.log(m.localeData());
<script src="https://momentjs.com/downloads/moment-with-locales.js"></script>

Extract TImestamp from the result of a Function

So I have an interface like this:
interface Test {
// ...
created_at: Timestamp;
// ...
}
and I return an object from a function like this:
export const getTest = functions.https.onCall(async (data, context) => {
if (!context.auth) {
return null;
}
let snap = await admin
.firestore()
.collection('test')
.get();
return snap.docs.map(r => ({ // Add id to the output
id: r.id,
...r.data()
})[0];
});
So I should be getting the timestamp object in my application, but this is what I get in the chrome console, when I try to get the object from the function like so:
// Using AngularFireFunctions
let result: Test = await this.fns.httpsCallable<void, Test>('getTest')().toPromise();
This is the whole content of result.created_at:
When I call result.created_at.toDate() I get an ....created_at.toDate is not a function error.
What can I do to change this?
This is what I am stuck with right now:
result.created_at = new Date(result.created_at._seconds * 1000);
It looks like you’re expecting the callable function to retain the data type of the objects returned from it. That’s not quite how it works. The function will serialize the passed objects as JSON, losing all object type information, including the Timestamp type. The Timestamp is being serialized using its internal representation, which is what you’re seeing in the log output. I wouldn’t write code that depends on this, as it's obviously using hidden implementation details.
What you should probably do instead is convert that Timestamp into a normal JavaScript object, and use that in the returned result. Then, on the client side, you will need to write code that understands how you’ve chosen to represent that timestamp. It is extra work, but it insulates the client from knowing those private implementation details.
I suggest putting the seconds and nanoseconds part of the Timestamp into a plain old object, replacing the existing Timestamp field, then converting that object back into a Timestamp on the client using the Timestamp constructor that takes the seconds and nanos components as arguments.

how does the ReadableMap interface in React-native convert JS to JAVA?

I'm trying to understand how to properly pass options from the js side of react-native to the java side.
The react-native bridge uses ReadableMap to convert but as a Java noob I'm failing to understand how this works.
More specifically I don't understand:
how the actual conversion works?
how to tell what type/format the downstream Java code wants?
how to properly use ReadableMap to do this?
Generally I would like to know how this works but I'll give the specific example I'm looking at to give some context.
A react-native package exposes a datetime picker.
The JS side has a showTimePicker method:
showTimePicker(date, callback) {
date = date || new Date();
console.log(this.props);
debugger
var options = {
...this.props,
hour:date.getHours(),
minute:date.getMinutes()
};
RCTDateTimePicker.showTimePicker(options, function (hour, minute) {
date.setHours(hour);
date.setMinutes(minute);
callback(date);
});
}
RCTDateTimePicker.showTimePicker is bridged to a Java method on the native side:
#ReactMethod
public void showTimePicker(ReadableMap options, Callback callback) {
DialogFragment timePicker = new TimePicker(options, callback);
timePicker.show(activity.getFragmentManager(), "timePicker");
}
which calls
public TimePicker(ReadableMap options, Callback callback) {
final Calendar c = Calendar.getInstance();
this.callback = callback;
hour = options.hasKey("hour") ? options.getInt("hour") : c.get(Calendar.HOUR_OF_DAY);
minute = options.hasKey("minute") ? options.getInt("minute") : c.get(Calendar.MINUTE);
}
which creates and instance of an Android TimePicker. My goal is to change the style of the Timepicker from watch to spinner.
There is a settable XML attribute android:timePickerMode="spinner" but I don't think I can pass an XML attribute through react-native can I?
I also found a suggestion in comments to pass defStyleAttr to do this, but I don't understand how.
First, see the list of Argument Types from the React Native document for Android Native Modules.
Argument Types
The following argument types are supported for methods
annotated with #ReactMethod and they directly map to their JavaScript
equivalents
Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
Callback -> function
ReadableMap -> Object
ReadableArray -> Array
So, you can pass the extra field for timePickerMode as a String by updating the options that the JS side passes to include it.
var options = {
...this.props,
hour:date.getHours(),
minute:date.getMinutes(),
timePickerMode:"spinner"
};
And then get that value from the ReadableMap in your custom TimePicker constructor.
String timePickerMode = options.hasKey("timePickerMode") ?
options.getString("timePickerMode") : defaultTimePickerMode;
Now you have the value you wish to set. Unfortunately it does not appear that timePickerMode can be set programmatically. This SO question asks how to do it and #alanv (whose profile indicates they are a Software Engineer at Google) indicates that it is not possible at runtime.

node.js log module bunyan change timezone

I'm using this logging module bunyan.js which is included in the framwork restify.js. The module does outprint a time in the log file/console, however, I want to change the time to UTC/GMT, not sure if it's possible wihtout modifying the module code?
If you don't want to use local time anywhere else in your process, one way to achieve what you want is to change the timezone for the process. Either by writing this statement at the startup of you application:
process.env.TZ = 'UTC'
Or by starting it with a environment variable from the command line, like this:
TZ=UTC node main.js
I was also facing the same issue and resolved it by adding a custom attribute, localtime, while creating the logger using bunyan.createLogger method like this:
var init = function () {
log = bunyan.createLogger({
name: 'myLogs',
src: true,
localtime: new Date().toString();
});
};
By doing this, I get an extra field in my log called localtime with the appropriate time as per my timezone.
Hope this helps.

Categories

Resources