I'm trying to get countdown.js to return something like this:
Months:Days:Weeks:Hours:Seconds
so something like this with two digits each:
11:02:12:06:12
So far I see the the countdown object has a constructor function which adds the hours and minutes labels, and I can't figure out how to remove them. Here is what I have so far:
var targetDate = new Date(2050, 00, 01);
var totalEnd = targetDate.setHours(targetDate.getHours() + 8);
var time = countdown( null, totalEnd, countdown.HOURS|countdown.MINUTES|countdown.SECONDS);
console.log(time);
Any help would be greatly appreciated. Thanks!
The Countdown.js provides methods
countdown.resetLabels();
countdown.setLabels(singular, plural, last, delim, empty, formatter);
The arguments:
singular is a pipe ('|') delimited ascending list of singular unit
name overrides
plural is a pipe ('|') delimited ascending list of plural unit name
overrides
last is a delimiter before the last unit (default: ' and ')
delim is a delimiter to use between all other units (default: ', ')
empty is a label to use when all units are zero (default: '')
formatter is a function which takes a number and returns a string
(default uses Number.toString()),
allowing customization of the way numbers are formatted, e.g., commas every 3 digits or some unique style that is specific to your locale.
The following would be effectively the same as calling countdown.resetLabels():
countdown.setLabels(
' millisecond| second| minute| hour| day| week| month| year| decade| century| millennium',
' milliseconds| seconds| minutes| hours| days| weeks| months| years| decades| centuries| millennia',
' and ',
', ',
'',
function(n){ return n.toString(); });
Make changes to the above method as per your requirement like (replace "and" & "," with ":")
countdown.setLabels(
' | | | | | | | | | | ',
' | | | | | | | | | | ',
':',
':',
'',
function(n){ return n.toString(); });
countdown(Start Date, End Date, countdown.YEARS | countdown.MONTHS | countdown.DAYS | countdown.HOURS | countdown.MINUTES | countdown.SECONDS , 5).toString();
Reference: http://countdownjs.org/readme.html (search for Localization)
This seemed to work for me:
var targetDate = new Date(2050, 00, 01);
var totalEnd = targetDate.setHours(targetDate.getHours() + 8);
var units = ~(countdown.MILLENNIA |
countdown.CENTURIES |
countdown.DECADES |
countdown.YEARS |
countdown.MINUTES |
countdown.MILLISECONDS);
var time = countdown( null, totalEnd, units);
console.log(time);
Related
I am working in Google sheets
I have a find and replace function gotten from here. It works great when the array is made from a single column of data
But, in certain instances in which I want to use my function I have all my data sitting in an array which is being passed from prior processing, the data if printed to the page looks like
| Id | Segment |Other Column| etc..
|----|--------------------|------------|
| 1 | AAA AA|AA|CaaL AA |stuff |
| 2 | AAA-AA|AA|CaaL |stuff |
| 3 | AAA, AA|AA|AA |AA |
| 4 | AA |stuff |
| 5 | AA AA | |
| 6 | AA, AA |AA |
| 7 | |stuff |
| 8 | CaaL |stuff |
| 9 | AA |stuff |
I only want to replace data in the Segment column
| Id | Segment ||Other Column| etc..
|----|-------------------|------------|
| 1 | AAA AA|zz|CaaL AA |stuff |
| 2 | AAA-AA|zz|Bob |stuff |
| 3 | AAA, AA|zz|zz |AA |
| 4 | zz |stuff |
| 5 | AA AA | |
| 6 | AA, AA |AA |
| 7 | |stuff |
| 8 | Bob |stuff |
| 9 | zz |stuff |
As it is the AA in the Other Column (could be in any column, I have no way of knowing) is being replaced which I do not want
Can the findReplace function be restricted to a single column in values updating that only that column in values ?
I have tried getting the column array I want to restrict values to with
function getColumn(matrix, col, startrow){
var column = [];
for(var i=startrow; i<matrix.length; i++){
column.push(matrix[i][col]);
}
return column;
}
and then attempting to restrict the input to this column
function fr(input) {
const aCOL = getColumn(values,2,0)
return input.aCOL.map(c => c.replace(regex, (x) => map[x]));
AND
return input.map(c => c.aCOL.map(y => y.replace(regex, (x) => map[x])));
}
I get Cannot read property 'map' of undefined
Thanks
function findReplace(values) {
var search_for = ["AA", "Caal"];
var replace_with = ["zz", "yy"];
var map = {};
search_for.forEach(function(item, i) {
map[item] = replace_with[i];
});
//map = { AA: 'zz', Caal: 'yy' };
const regex = new RegExp("(?<![^|])(?:" + search_for.join("|") + ")(?![^|])", "g");
range.setValues(values.map(fr));
function fr(input) {
return input.map(c => c.replace(regex, (x) => map[x]));
}
}
The code you got from your previous question works fine if you just change the range you're retrieving. So instead of creating a function to extract the column into an array, you can just adjust the range.
If the column you want to replace ('Segment') is the second one, then you can do the following changes.
From:
const col = ss.getRange(2, 3, ss.getLastRow()).getValues();
...
ss.getRange(2, 3, ss.getLastRow()).setValues(col.map(fr));
To:
const col = ss.getRange(2, 2, ss.getLastRow()).getValues();
...
ss.getRange(2, 2, ss.getLastRow()).setValues(col.map(fr));
I have this quite long string that contains multiple information. So I guess we can say that its a couple of fields concatenated together without any delimiters. I understand that to make this work, all of the lengths of the fields should always be fixed. However, two of the fields represent a name and an amount and no prefixes/suffixes were implemented to maintain a fixed length.
I was wondering how would I got about this problem? Here's a sample of the string and how they should be separated:
Sample #1
Actual Input:
48001MCAbastillas2200800046300017100518110555130000123
How it should be separated:
480 | 01 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 130000 | 123
Sample #2
Actual Input:
48004MCAbastillas22008000463000171005181105555000000123
How it should be separated:
480 | 04 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 5000000 | 123
In my example only the amount has changed but I'm expecting that the name will vary in length as well. Any suggestion will be much appreciated.
I'd probably use a regular expression for this.
String test = "48004MCAbastillas22008000463000171005181105555000000123";
Pattern pattern = Pattern.compile("^(\\d{3})(\\d{2})([A-Za-z]+)(\\d{16})(\\d{6})(\\d{6})(\\d+)(\\d{3})$");
Matcher matcher = pattern.matcher(test);
if (matcher.matches())
{
for (int i = 1; i <= matcher.groupCount(); ++i)
{
System.out.print(matcher.group(i) + " | ");
}
}
Sample output:
480 | 04 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 5000000
| 123 |
Note that the third and second to last groups do not have fixed lengths.
It's more difficult if the name can contain numbers. My approach would be to run this against the data that you have and print a list of anything that doesn't match (i.e. add an else clause). Perhaps then you can come up with a better strategy for handling these cases. For example, something like ([A-Za-z]+\w*[A-Za-z]+) might be an improvement, because that will at least allow numbers in the middle of the name.
Sometimes you just have to accept that when the data you're given is crap, you just have to do the best that you can and that might mean throwing some of it away.
We want the output
480 | 01 | MCAbastillas | 2200800046300017 | 100518 | 110555 | 130000
| 123
where the fields 3 and 7 had no fixed length.
Suppose that we store the string in a string var:
String s="48001MCAbastillas2200800046300017100518110555130000123";
We can find the fields 1 & 2 easly:
System.out.println(s.substring(0, 3)); //has 3 digit
System.out.println(s.substring(3, 5)); //has 2 digit
//we can reduce s
s=s.substring(6); //remove char from 0 to 5 included
If you'll call System.out.println(s); you well see
CAbastillas2200800046300017100518110555130000123
Now we have the string... I can deduce that it is composed only by char. So we have to find the first occurrence of a number... We can use a cycle:
int index=-1;
for( int i=0; i<s.length(); i++ ) {
if( Character.isDigit(s.charAt(i))) {
index=i;
System.out.println("There is a number in the position "+ index);
break;
}
}
Now you can extract your name with:
System.out.println(s.substring(0, index));
and extract the other 3 fields (you can optimize this part...)
System.out.println(s.substring(0, 16));
s=s.substring(16);
System.out.println(s.substring(0, 6));
s=s.substring(6);
System.out.println(s.substring(0, 6));
s=s.substring(6);
Finally, you can divide the remaining s in two part with length s.length.3 and 3:
System.out.println(s.substring(0, s.length()-3));
System.out.println(s.substring( s.length()-3,s.length()));
Your output will be:
480
01
There is a number in the position 11
CAbastillas
2200800046300017
100518
110555
130000
123
My question is very brief. I am new to TypeScript, been searching around here and there but didn't find yet an answer.
Does any experienced TypeScripter know if there is a character Type or an easy way to achieve one?
TypeScript does not have a type for representing fixed-length strings.
I'm not sure about easy, but you could sorta do something with string literal types:
type Char = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k'
| 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x'
| 'y' | 'z' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K'
| 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X'
| 'Y' | 'Z' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' // etc....;
of course, this is a fairly brittle solution and breaks down when you consider unicode characters, and I wouldn't really suggest it. As Ryan mentions, JavaScript itself doesn't have any notion of a fixed length string, nor the concept of a char as distinct from a string.
You could use a regex within TypeGuard to contain it's type eg:(you can declare an empty enum to get a new type to be associated with the type guard)
enum CharType { }
export type Char = string & CharType
const isChar = (str: string): str is Char => /^(.|\n)$/.test(
str
)
export function toChar(c: string): Char {
//you can also use is char here for to test whether actually is char
if (!isChar(c)) {
throw new Error('not a char')
}
return c
}
Now Char matches only things that come from calling char(eg actually casted by calling the function rather than just asserted on build time. The compiler simply accepts that a Char is returned and that's actually true if you think of it since it will just throw otherwise)
Original Source(applied to date string):
Atomic Object
Assumptions:
I assume that by mentioning typescript you mean a type used for compile-time checks by typescript compiler and not looking for any kind of optimization on the actual compiled js side(since js only has strings)
The only issue I can see is that you can pass whatever to char function and it will only throw at run time. But you will never reach to a state where you expect a Char and you get something else(since Chars only come from calling char).
On a side note even java casts throw just runtime exceptions.
Although the above approach might not have much to do with casts, I do find some commonalities...
In some comments and answers the lack of a small type of size 8-bit in JavaScript was pointed out. Well, thats not entirely true. With TypedArrays we can create a type of size similar to a classical C-like char. Here a quick take by utilizing Uint8ClampedArray.
type CharString = '!'|'"'|'#'|'$'|'%'|'&'|"'"|'('|')'|'*'|'+'|','|'-'|'.'|'/'|'0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'|':'|';'|'<'|'='|'>'|'?'|'#'|'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'I'|'J'|'K'|'L'|'M'|'N'|'O'|'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'X'|'Y'|'Z'|'['|'\\'|']'|'^'|'_'|'`'|'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'|'k'|'l'|'m'|'n'|'o'|'p'|'q'|'r'|'s'|'t'|'u'|'v'|'w'|'x'|'y'|'z'|'{'|'|'|'}'|'~';
type CharNumber = 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175|176|177|178|179|180|181|182|183|184|185|186|187|188|189|190|191|192|193|194|195|196|197|198|199|200|201|202|203|204|205|206|207|208|209|210|211|212|213|214|215|216|217|218|219|220|221|222|223|224|225|226|227|228|229|230|231|232|233|234|235|236|237|238|239|240|241|242|243|244|245|246|247|248|249|250|251|252|253|254|255;
class Char extends Uint8ClampedArray {
constructor(char: CharNumber | CharString | Char) {
super(1);
this.setValue(char);
}
get _value(): CharNumber {
return this[0] as CharNumber;
}
set _value(char: CharNumber | CharString | Char) {
if (char instanceof Char) {
this[0] = char._value;
} else if (typeof char === 'number') {
this[0] = char;
} else if (typeof char === 'string') {
this[0] = char.charCodeAt(0);
}
}
setValue(char: CharNumber | CharString | Char) {
this._value = char;
}
toString(): CharString {
return String.fromCharCode(this._value) as CharString;
}
[Symbol.toPrimitive](hint) {
if (hint === 'number') {
return this.toNumber();
}
return this.toString();
}
toNumber(): CharNumber {
return this._value;
}
}
function char(c: CharNumber | CharString | Char) {
return new Char(c);
}
const messageInChars = [
char(72),
char(101),
char(108),
char(108),
char(111),
char(32),
char(83),
char(116),
char(97),
char(99),
char(107),
char(79),
char(118),
char(101),
char(114),
char(102),
char(108),
char(111),
char(119),
];
console.log('char array as string:', messageInChars.join(''));
console.log('calculating with chars:', +messageInChars[0] + +messageInChars[1]);
Thoughts:
In the example, I am using numbers to initialize the Chars. As numbers are doubles, for the short moment of initialization I assume more memory is needed, but not at rest.
Further, I am not entirely sure what extending a TypedArray does to its instance's size.
old answer
A Char is simply a number. Since the basic types of TypeScript do not include Chars what you could do is store a number and convert it back and forth:
var number = "h".charCodeAt(0);
var char = String.fromCharCode(number)
And to something like:
class Char {
private _value:Number;
constructor(char: Number | String){
this.setValue(char);
}
get getValue():String {
return String.fromCharCode(this._value);
}
set setValue(char: Number | String) {
if (typeof char === "number") {
this._value = char;
}
else {
this._value = char.charCodeAt(0);
}
}
}
As I know, the basic types of typescript don't include char.
As a slightly more concise method than listing out all letter characters, you can list out all upper-case or all lower-case characters, then use Lowercase or Uppercase to change their capitalization and unify with the previous type.
type UpperCaseCharacter = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';
// add additional non-letter characters to this union as desired
type Character = UpperCaseCharacter | Lowercase<UpperCaseCharacter>;
You could just define a wrapper around string, and throw an error if the string is more than one character.
class Character {
readonly char: string;
constructor(char: string) {
if(char.length !== 1) {
throw new Error(char + " is not a single character");
}
this.char = char;
}
toString(): string {
return this.char;
}
}
////////////////////////////////////////
var good: Character = new Character("f");
var bad: Character = new Character("foo"); //error
Of course, you can also add helper methods to the class which operate on the string like toLowerCase(), toUpperCase(), etc.
What does the +d in
function addMonths(d, n, keepTime) {
if (+d) {
mean?
The + operator returns the numeric representation of the object. So in your particular case, it would appear to be predicating the if on whether or not d is a non-zero number.
Reference here. And, as pointed out in comments, here.
Operator + is a unary operator which converts the value to a number. Below is a table with corresponding results of using this operator for different values.
+----------------------------+-----------+
| Value | + (Value) |
+----------------------------+-----------+
| 1 | 1 |
| '-1' | -1 |
| '3.14' | 3.14 |
| '3' | 3 |
| '0xAA' | 170 |
| true | 1 |
| false | 0 |
| null | 0 |
| 'Infinity' | Infinity |
| 'infinity' | NaN |
| '10a' | NaN |
| undefined | NaN |
| ['Apple'] | NaN |
| function(val){ return val }| NaN |
+----------------------------+-----------+
Operator + returns a value for objects which have implemented method valueOf.
let something = {
valueOf: function () {
return 25;
}
};
console.log(+something);
It is a unary "+" operator which yields a numeric expression. It would be the same as d*1, I believe.
As explained in other answers it converts the variable to a number. Specially useful when d can be either a number or a string that evaluates to a number.
Example (using the addMonths function in the question):
addMonths(34,1,true);
addMonths("34",1,true);
then the +d will evaluate to a number in all cases. Thus avoiding the need to check for the type and take different code paths depending on whether d is a number, a function or a string that can be converted to a number.
I have the following regex patterns that matches all the 'act' that ends with numbers within a list of URLs.
Regex pattern /\/ch(\d+)\/act(\d+)/gi
Javascript code
pageSrc[1] = "../ch01/index.html";
pageSrc[2] = "../ch01/act01/1.html";
pageSrc[3] = "../ch01/act01/2.html";
pageSrc[4] = "../ch01/act02/1.html";
pageSrc[5] = "../ch01/act02/2.html";
pageSrc[6] = "../ch01/actx/1.html";
var pattern = /\/ch(\d+)\/act(\d+)/gi;
for(var i=0; i<pageSrc.length; ++i){
var hasAct = pattern.test(pageSrc[i]);
console.log(hasAct);
}
The expected results and actual results
| String | Expected Result | Actual Result |
| pageSrc[1] | false | false |
| pageSrc[2] | true | true |
| pageSrc[3] | true | *FALSE |
| pageSrc[4] | true | true |
| pageSrc[5] | true | *FALSE |
| pageSrc[6] | false | false |
Am not sure why pageSrc[3] won't return true. I used the regEx tester on gskinner.com and it worked fine, here is the link http://gskinner.com/RegExr/?344ap
Can anyone help me take a look please? thanks in advance!
Remove the g flag. From the RegExp.test documentation:
As with exec (or in combination with it), test called multiple times on the same global regular expression instance will advance past the previous match.
You don't want a global search when reusing a pattern like this.
> var pageSrc = [];
> pageSrc[1] = "../ch01/index.html";
pageSrc[2] = "../ch01/act01/1.html";
pageSrc[3] = "../ch01/act01/2.html";
pageSrc[4] = "../ch01/act02/1.html";
pageSrc[5] = "../ch01/act02/2.html";
pageSrc[6] = "../ch01/actx/1.html";
var pattern = /\/ch(\d+)\/act(\d+)/i;
for(var i=0; i<pageSrc.length; ++i){
var hasAct = pattern.test(pageSrc[i]);
console.log(i, hasAct);
}
0 false
1 false
2 true
3 true
4 true
5 true
6 false
You are using /g. Remove that flag to make it work.
The g flag makes the regex start matching from pattern.lastIndex (the index where the previous match ended), until it fails, and then start at 0.