DataviewJS Snippet Showcase

Topic

Summary
  • How to filter the data by the filename of a link?

Structures

Summary

case_YAML_Y-YYY

The Note Structure

case_YAML_Y-YYY: To use nested YAML fields where the single root YAML contains multiple correlated sub-YAMLs that are repeated or not

YAML: To use YAML
Y: the single root YAML
-YYY: multiple correlated sub-YAMLs that are repeated or not

Example10: the sub-YAMLs are not repeated

Take the following file as an example.
-YYY: purchases.store, purchases.item, purchases.comments

---
date: 1992-06-01
purchases:
  - store: "[[some store]]"
    item: some item
    comments: comments
---

The Data Structure
let slice_pages = {
    date: "1992-06-01T00:00:00.000Z",
    purchases: [
        {
            store: "[[some store]]",
            item: "some item",
            comments: "comments",
        },
    ],
};

Example11: the sub-YAMLs are repeated

Take the following file as an example.
-YYY: purchases.store, purchases.item, purchases.comments

---
date: 1992-03-01
purchases:
  - store: "[[some store]]"
    item: some item
    comments: comments
  - store: "[[another store]]"
    item: another item
    comments: other comments
---

The Data Structure
let slice_pages = {
    date: "1992-03-01T00:00:00.000Z",
    purchases: [
        {
            store: "[[some store]]",
            item: "some item",
            comments: "comments",
        },
        {
            store: "[[another store]]",
            item: "another item",
            comments: "other comments",
        },
    ],
};

Test

Summary
  • dataview: v0.5.46

input

Summary

dictionary files: for DQL10

  • Location: “100_Project/02_dataview/Q17_Purchases/Q17_test_data”

03

  • filename : dic_19920301
---
date: 1992-03-01
purchases:
  - store: "[[some store]]"
    item: some item
    comments: comments
  - store: "[[another store]]"
    item: another item
    comments: other comments
---



04

  • filename : dic_19920401
---
date: 1992-04-01
purchases:
  - store: "[[some store]]"
    item: apples
    comments: 
  - store: "[[some store]]"
    item: oranges
    comments: 
---



05

  • filename : dic_19920501
---
date: 1992-05-01
purchases:
  - store: "[[another store]]"
    item: potatoes, potatoes
    comments: 
  - store: "[[another store]]"
    item: a very big watermelon
    comments: 
---



06_a_root_YAML_and_its_children

  • filename : dic_19920601
---
date: 1992-06-01
purchases:
  - store: "[[some store]]"
    item: some item
    comments: comments
---



07_including_an_empty_record

  • filename : dic_19920701
---
date: 1992-07-01
purchases:
  - store: "[[some store]]"
    item: some item
    comments: comments
  - store: 
    item: 
    comments: 
---



08_null

  • filename : dic_19920801
---
date: 1992-08-01
purchases:
---



09_undefined

  • filename : dic_19920901
---
date: 1992-09-01
---



10_excluding_store_not_link

  • filename : dic_19921001
---
date: 1992-10-01
purchases:
  - store: "another store"
    item: another item
    comments: comments
---



DQL10_filter_by_filename_of_a_link: case_YAML_Y-YYY

Summary

Main DQL

Code Name Data type Group By Purposes Remark
DQL10_filter_by
_filename_of_a_link
P.store:
a link
no 0.To require the note structure like case_YAML_Y-YYY
1.To filter by purchases
2.To break up a list like purchases in a file into each individual P in a file and let P = each element of purchases of each page
3.To filter by P and P.store
4.To define a field variable s_filename_of_link
5.To filter by s_filename_of_link
6.To sort by date in descending order
7.To display the result as a table
The Regular Expression in the DQL10 is based on the DQL10 in the following topic.
- Solutions: by Justdoitcc

Code DQL10_filter_by_filename_of_a_link: case_YAML_Y-YYY

Summary_code
title: DQL10_filter_by_filename_of_a_link =>0.To require the note structure like case_YAML_Y-YYY 1.To filter by `purchases` 2.To break up a list like `purchases` in a file into each individual `P` in a file and let P = each element of `purchases` of each page 3.To filter by `P` and `P.store` 4.To define a field variable `s_filename_of_link` 5.To filter by `s_filename_of_link` 6.To sort by `date` in descending order 7.To display the result as a table
collapse: close
icon: 
color: 
```dataview
TABLE WITHOUT ID 
      file.link AS "File",
	  P.store AS "store",
	  P.item AS "item",
	  P.comments AS "comments",
      s_filename_of_link AS "filename_of_store"
      
FROM "100_Project/02_dataview/Q17_Purchases/Q17_test_data"
WHERE purchases != null       

FLATTEN purchases AS P
WHERE P != null AND P.store != null
FLATTEN regexreplace(meta(P.store).path, "^(.*/)(.+)(\.md)$", "$2") AS s_filename_of_link
WHERE contains(s_filename_of_link, "another store")
SORT date DESC
```

Screenshots(DQL10)


Oh! I didn’t know this is possible!
That’s why I developed my plugin “Table to CSV Exporter”. :wink:

1 Like

I just started using Obsidian a few days ago as a daily journal and finally got my first dataviewjs query working this morning!

It’s nothing too fancy, especially compared to the query in the OP of this thread, but I just wanted to share my little success. My query creates a table of people mentioned in my daily notes, sorted by most recent mention, a count of mentions, and shows me their relationship to me (friend, family, work).

The thing that made this a bit complicated to setup (for me as a newbie) was that I wanted it be completely automatic and not require any manual editing of YAML. I initially had a field in each person’s note that I would have had to update with the date of our last meetup, but instead I found a way to get the latest daily note and use that as the date.

I also originally had a field for relationship, but since I already had everything set up in folders I figured that there might be a way to inherit that directly from the folder structure, and there was.

So here is what the end result looks like…

In my fault I have a folder called “People” and sub-folders in it that have an individual note for every person like this:

image

And my query gives me this table:

// Get the latest daily note mentioning this person. Daily notes must be named so that most recent is latest alphabetically.
function latestDailyNote(k) {
	let notes = k.file.inlinks;
	notes = notes.map(n => dv.page(n));
	notes = notes.where(n => n.file.folder == "Daily Journal");
	notes = notes.map(n => n.file.name);
	notes = notes.sort(n => n,'desc');
	return notes[0];
}

dv.table(["Name", "Relationship", "Mentions", "Last Mention"], dv.pages('"People"')
	.where(p => !p.file.link.equals(dv.current().file.link)) // Must use equals(), == fails because not both strings?
	.sort(p => latestDailyNote(p), 'desc')
    .map(p => [
	    p.file.link, 
	    p.file.folder.split("/")[p.file.folder.split("/").length-1],
	    p.file.inlinks.length, 
	    latestDailyNote(p)]))

I’ve probably written this in an unnecessarily convoluted way as I have zero experience in javascript. I’m just happy that the thing actually works, but would welcome any improvements, especially ones that might make it more efficient.

One thing that caused me a lot of problems in particular was working with links. It seems that links don’t necessary sort by the text of the link. Does anyone know how an array of links is sorted? In the end I settled for using dv.page to get the page of the link and then file.name to get the text of the link and sorting on that.

1 Like

I’m trying to do a dv.table without the counts in the headers.

Anyone has an idea how to do so? I’m seeing

https://github.com/blacksmithgu/obsidian-dataview/search?q=values.length

and it appears there is no configuration option. At the same time, I see many people posting screenshots of examples where there are no counters in the headers.

See here:

Generated like this:

---
title: Meetings
days: -10
---

# Upcoming Meetings

```dataviewjs
Date.prototype.addDays = function(days) {
    var date = new Date(this.valueOf());
    date.setDate(date.getDate() + days);
    return date;
}

function sortDate(a, b) {
	return new Date(a) < new Date(b);
}

function padTo2Digits(num) {
  return num.toString().padStart(2, '0');
}

function formatDate(date) {
	date.setHours(0, 0, 0, 0);
  return [
    date.getFullYear(),
    padTo2Digits(date.getMonth() + 1),
    padTo2Digits(date.getDate()),
  ].join('-');
}

let pg = dv.current(); 

let pages = dv.pages("#meeting")
	.where(p =>
		   p.date
		&& p.file.name != pg.file.name
		&& new Date().addDays(pg.days) <= new Date(p.date)
	)
	.sort(p => p.date, "desc", sortDate)
;

for (let group of pages.groupBy(
			b => formatDate(new Date(b.date))
		)
	) { 
	dv.table(
		  [group.key, "Meeting"],
			group.rows
			  .map(k => [ k.date, k.file.link ] 
			) 
		); 
}

I’m sure this is stupidly easy question but I’m a javascript novice and I’ve been working an (unrelated) update all night. Googling skills haven’t helped, so can someone assist?

I have an inline dataviewjs script and all I want to do is a case-insensitive string compare. In straight dataview I’ve been doing this: WHERE contains(lower(muddle),“blarg”)

where ‘muddle’ is defined in YAML.

In my inline dataviewjs script I have .where( k => k.muddle == “blarg”) which works as long as the case fully matches but I haven’t been able to force ‘k.muddle’ to lowercase. toLowerCase, lower, etc. have been tried as a result of google searches.

Trying to get some magic with Dashboard++…

Help? Thanks!

Topic

Summary
  • How to hide the file count in the_nth_of_table dataview table?
  • How to hide the file count in each dataview table?

Using DVJS

Summary_DVJS

Hide the file count in the the_nth_of_table dataview table

```JS
// M91. hide the file count in the `the_nth_of_table` dataview table :
// #####################################################################
let the_nth_of_table = 2;
this.container.querySelectorAll(
    ".table-view-table tr:first-of-type th:first-of-type > span.small-text"
)[the_nth_of_table - 1].style.visibility = "hidden";
```

Hide the file count in each dataview table

```JS
// M99. hide the file count in each dataview table :
// #####################################################################
let css_Lists = this.container.querySelectorAll(
    ".table-view-table tr:first-of-type th:first-of-type > span.small-text"
);
for (let i = 0; i < css_Lists.length; i++) {
    css_Lists[i].style.visibility = "hidden";
}
```

Using CSS snippet

Summary_CSS
```CSS
// C99. hide the file count in each dataview table :
// #####################################################################
.dataview.small-text {
  display: none;
}
```

Reference

Summary

Topic

Summary
  • How to use dv.func.contains in a case-sensitive string comparison?
  • How to use dv.func.icontains in a case-insensitive string comparison?

Test

Summary
  • dataview: v0.5.46

Input

Summary

dictionary files:

  • Location: “100_Project/01_dataviewjs/01_by_example/Q84_Contains/Q84_test_data”

folder: 03

  • filename : dic_19850301
---
Date: 1985-03-01
muddle: BLARG123 abc
---


folder: 04

  • filename : dic_19850401
---
Date: 1985-04-01
muddle: BLARG abc
---


folder: 05

  • filename : dic_19850501
---
Date: 1985-05-01
muddle: blarg456 abc
---


folder: 06

  • filename : dic_19850601
---
Date: 1985-06-01
muddle: blarg abc
---


DVJS10_icontains_and_TABLE

Summary

Main DVJS

Code Name Data type Group By Purposes Remark
DVJS10_icontains_and_TABLE muddle:
a string
no 1.To filter by muddle(An existence check)
2.To filter by muddle(case-insensitive)
3.To display the result as a table

Notes

Summary

The same codes:

  • To filter by muddle(case-insensitive)
Original Example10: DVJS
```JS
.where((page) => dv.func.contains(page.muddle.toLowerCase(), "blarg"))
```
Another Example11: DVJS
```JS
.where((page) => dv.func.contains(dv.func.lower(page.muddle), "blarg"))
```
Another Example12: DVJS
```JS
.where((page) => dv.func.icontains(page.muddle, "blarg")) 
```
Another Example21: DQL
```SQL
WHERE contains(lower(muddle), "blarg")
```
Another Example22: DQL
```SQL
WHERE icontains(muddle, "blarg")
```

Code DVJS10_icontains_and_TABLE

Summary_code
title: DVJS10_icontains_and_TABLE =>1.To filter by muddle(An existence check) 2.To filter by muddle(case-insensitive) 3.To display the result as a table
collapse: close
icon: 
color: 
```dataviewjs
// M11. define pages: gather relevant pages
// #####################################################################
let pages = dv
    .pages(
        '"100_Project/01_dataviewjs/01_by_example/Q84_Contains/Q84_test_data"'
    )
    .where((page) => page.muddle)
    .where((page) => dv.func.contains(page.muddle.toLowerCase(), "blarg"));
    //.sort((page) => page.file.name, "desc");


// M31.Output :
// #####################################################################
//dv.header(2, "pp"); //org
dv.table(
    ["File", "muddle"],
    pages.map((page) => [page.file.link, page.muddle])
);





Screenshots(DVJS10):


2 Likes

Thanks! That solved it. I can see I’m going to need a JavaScript course. Most of my coding was 10+ years ago and in C, C++ or Perl 5. Rust, so much rust…

2 Likes

I modified your countdown method, adding a dateDiff method using Mordred’s answer from this stackoverflow question. Now the table shows that their birthday date is 1 month(s) 20 Day(s) away.

var start = moment().startOf('day');
var end = moment(start).add(dv.current().duration);
var dateformat = "YYYY-MM-DD";
if (dv.current().dateformat) { dateformat = dv.current().dateformat; }

// info text above table, {0}=duration, {1}=start date, {2}=end date
// parameters can be left out, or the string empty
var infotext = "Upcoming birthdays for {0} from now ({1} – {2})<br><br>";

//======================================================================

function nextBirthday(birthday) {
    // Get person’s next birthday on or after "start"
    // returns a moment
    
    // need to "unparse" because DV has already converted YAML birthday to DateTime object
    // shouldn’t harm if already a string
    var bday = moment(birthday.toString());
    var bdayNext = moment(bday).year(start.year());
    if (bdayNext.isBefore(start, 'day')) {
        bdayNext.add(1, "year");
    }
    return bdayNext;
}

function turns(birthday) {
    // Get the age in years a person will turn to on their next birthday

    // need to "unparse" because DV has already converted YAML birthday to DateTime object
    // shouldn’t harm if already a string
    var bday = moment(birthday.toString());
    return nextBirthday(birthday).diff(bday, 'years');
}

function dateDiff(startingDate, endingDate) {
	let startDate = new Date(new Date(startingDate).toISOString().substr(0, 10));
	if (!endingDate) {
		endingDate = new Date().toISOString().substr(0, 10); // need date in YYYY-MM-DD format
	}
	
	let endDate = new Date(endingDate);
	
	if (startDate > endDate) {
		const swap = startDate;
		startDate = endDate;
	    endDate = swap;
	}
	
	const startYear = startDate.getFullYear();
	const february = (startYear % 4 === 0 && startYear % 100 !== 0) || startYear % 400 === 0 ? 29 : 28;
	const daysInMonth = [31, february, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
		
	let yearDiff = endDate.getFullYear() - startYear;
	let monthDiff = endDate.getMonth() - startDate.getMonth();
	
	if (monthDiff < 0) {
		yearDiff--;
		monthDiff += 12;
	}
	
	let dayDiff = endDate.getDate() - startDate.getDate();
	
	if (dayDiff < 0) {
		if (monthDiff > 0) {
			monthDiff--;
		} else {
			yearDiff--;
			monthDiff = 11;
		}
		dayDiff += daysInMonth[startDate.getMonth()];
	}
	
	return monthDiff + ' Month(s) ' + dayDiff + ' Day(s) away';
}

function countdown(birthday){
	var bday = moment(birthday.toString())
	const setTime = new Date(bday);
	const nowTime = new Date();
	const dateDifference = dateDiff(nowTime, setTime);
	
	return dateDifference;	
}

function showBirthday(birthday) {
    // Determine if this birthday is in the range to be shown
    // including the start date, excluding the end date
    // because that comes from a duration calculation
    // for use with "where", returns true or false
    
    if (birthday) {
        // need to "unparse" because DV has already converted YAML birthday to DateTime object
        // shouldn’t harm if already a string
        var bday = moment(birthday.toString());
        var bdayNext = nextBirthday(birthday);
        if (bdayNext.isBetween(start, end, 'day', '[)')) {
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

function sortByNextBirthday(a, b) {
    // comparator function for "sort"
    
  if (nextBirthday(a).isBefore(nextBirthday(b))) {
    return -1;
  }
  if (nextBirthday(a).isAfter(nextBirthday(b))) {
    return 1;
  }
  // they’re equal
  return 0;
}


//======================================================================

dv.paragraph(infotext.format(moment.duration(dv.current().duration.toString()).humanize(), start.format(dateformat), end.format(dateformat)));

dv.table(
    ["Name", "Birthday", "Turns", "Countdown"],
    dv.pages(dv.current().searchterm)
        // use a function to see if this birthday is in range to be shown
        .where(p => showBirthday(p.birthday))
        // use a comparator function to sort by next birthday
        .sort(p => p.birthday, 'asc', sortByNextBirthday)
        .map(p => [
            p.file.link,
            p.birthday ? nextBirthday(p.birthday).format(dateformat) : '–',
            turns(p.birthday),
			countdown(nextBirthday(p.birthday)),
        ])
);
5 Likes

Hey, thanks for a great JS code. I tried to make it work but i didnt succed.
I put these in the front matter:

birthday: 2000-01-01
#searchterm: "#family or #friends"
searchterm: '"People"'
duration: 1 year

And added the code in another note as a plain text, unfortunate i just see the code but it doesnt run, what did i do wrong?
Thanks.

Hello all, I’m sure this is probably very easy, but I’m a bit new to dataview.

I would like to use dataview to build a table (not a dataview TASK view) that includes a column with the note name and link (the first column) and a column with the text of the first uncomplete task that appears on that page. I’ve been trying all day to figure this out and nothing I do seems to come even close.

Many thanks in advance!

Last july, @Moonbase59 , created a script to list the current hotkeys, and I got news of this today. I discovered that if multiple keys was defined, it didn’t show the alternate keys provided, so I modified the scripts a little.

Modifications I made to script include:

  • Allowing for showing multiple keys for a given command
  • Simplified the join operations on the modifiers, and allowed for usage of symbols, if one are so inclined
  • Changed the second listing to only show commands without a hotkey, and as a result I also removed the hotkey column for that listing
  • Provided in-code examples of how to sort on either columns by changing which .sort() command is commented or not

With these listing I can now easier find conflicting hotkeys (even if more than two commands use the same key combination), and also easier see commands available for hotkeys.

New variant of Commands vs Hotkeys

### Commands with hotkeys sorted by name
```dataviewjs

function joinModifiers(modifiers, symbols=false) {
	return modifiers.join(' ')
	                .replace('Mod', symbols ? '⌘' : 'CMD')
    	            .replace('Alt', symbols ? '⌥' : 'OPT')
    	            .replace('Ctrl', symbols ? '⌃' : 'CTRL')
    	            .replace('Shift', symbols ? '⇧' : 'SHIFT')
}

function getHotkey(arr, highlight=true) {
    let hi = highlight ? '**' : '';
    let keys = []; // Store all key combinations defined for this command
    let currKey = ""

    // Find the default key setting for the command, if any
    if (arr.hotkeys && arr.hotkeys.length > 0) {
      console.log(arr.hotkeys)
      for (let aKey of arr.hotkeys) {
    	 keys.push(joinModifiers(aKey.modifiers) + ' ' + aKey.key)
      }
    }
      
    // Handle custom hotkey setup, with possible multiple assignments
    let ck = app.hotkeyManager.customKeys[arr.id];
    if (ck) { 
      // Reset keys array, as custom keys override the default key setting
      keys = []
      for (let aKey of ck) {
    	 keys.push(hi + joinModifiers(aKey.modifiers) + ' ' + aKey.key + hi)
      }
    } 
    
	return (keys.length != 0) ? keys.join('<br />') : 'none';
}

let cmds = dv.array(Object.entries(app.commands.commands))
    .where(v => getHotkey(v[1]) != 'none')
    //// Choose your sorting option by changing which line is commented out
    .sort(v => v[1].id, 'asc'); // Sorted by the command name
    // .sort(v => v[1].id, 'asc'); // Sorted by the descriptive name
    //.sort(v => getHotkey(v[1], false), 'asc'); // Sorted by hotkey

dv.paragraph(cmds.length + " hotkeys. " +
    "Both 'default' and <strong>'custom'</strong>.<br><br>");

dv.table(["Command", "Name", "Hotkeys"],
  cmds.map(v => [
    v[1].id,
    v[1].name,
    getHotkey(v[1]),
    ])
  );
```

### Other available commands with no key assigned

```dataviewjs

function getHotkey(arr, highlight=true) {
    let hi = highlight ? '**' : '';
    let keys = []; // Store all key combinations defined for this command
    let currKey = ""

    // Find the default key setting for the command, if any
    if (arr.hotkeys && arr.hotkeys.length > 0) {
      console.log(arr.hotkeys)
      for (let aKey of arr.hotkeys) {
    	 keys.push(aKey.modifiers.join(' ')
    	               .replace('Mod', 'CMD')
    	               .replace('Alt', 'OPT')
    	               .replace('Ctrl', 'CTRL')
    	               .replace('Shift', 'SHIFT')
    	            + ' ' + aKey.key);
      }
    }
      
    // Handle custom hotkey setup, with possible multiple assignments
    let ck = app.hotkeyManager.customKeys[arr.id];
    if (ck) { 
      // Reset keys array, as custom keys override the default key settings
      keys = []
      for (let aKey of ck) {
    	 keys.push(hi + aKey.modifiers.join(' ')
    	                .replace('Mod', 'CMD')
    	                .replace('Alt', 'OPT')
    	                .replace('Ctrl', 'CTRL')
    	                .replace('Shift', 'SHIFT')
    	              + ' ' + aKey.key + hi)
      }
    } 
    
	return (keys.length != 0) ? keys.join('<br />') : 'none';
}

let cmds = dv.array(Object.entries(app.commands.commands))
    .where(v => getHotkey(v[1]) == 'none')
    //// Choose your sorting option by changing which line is commented out
    .sort(v => v[1].id, 'asc'); // Sorted by the command name
    // .sort(v => v[1].id, 'asc'); // Sorted by the descriptive name
    //.sort(v => getHotkey(v[1], false), 'asc'); // Sorted by hotkey

dv.paragraph(cmds.length + " commands. " +
    "Rest of commands which doesn't have any keys assigned to them.<br><br>");

dv.table(["Command", "Name"],
  cmds.map(v => [
    v[1].id,
    v[1].name])
  );
```

In the image below you can see the top part of the hotkeys currently defined for me, with some interesting (constructed!) conflicts.

See for example how Cmd P is connected to both opening the command palette, opening a daily note, and open the next daily note. Kind of stupid setup, so I need to fix that soon! :grin:

In addition one can see that for the first command, Navigate back, both Cmd Home and Opt ArrowLeft are valid combinations.

Whilst working with this we’ve got a FR re-opened, see A way to find which command is bound a specific hotkey, so please show some love to that, to get more attention to issues related to resolving hotkey conflicts, and to locate what a given command does.

I also found a plugin, see forum post in Show only assigned hotkeys - #3 by ichmoimeyo, which could display hotkeys on a visual image of the keyboard. Sadly, it’s in the early stages of development, and it doesn’t do the correct thing on Mac (as of today).

3 Likes

This question was also posted in the Help category, and solved there.

is it possible to create a bar chart from sum of different inlinefield ?

İ have a tag logbook and inlinefield games:: I ve been trying this one month now :frowning: I am using obsidian charts

Solutions

This is awesome but there is a small typo:

    // .sort(v => v[1].id, 'asc'); // Sorted by the descriptive name

Should say

    // .sort(v => v[1].name, 'asc'); // Sorted by the descriptive name

Cheers

1 Like

I have gotten my Birthday list to work thanks to this post and have been using it quite happily for a while.

But I’ve come across something I can’t figure out. I want to ask and answer the question “How old will person be ON their birthday THIS year?”

So if I have the following file:

# Person Name
Start-Date:: 1980-12-05
Details:: turns `=date(date(today).year + "-" + this.Start-Date.month + "-" + this.Start-Date.day) - this.Start-Date`  in `=date(today).year`

results in a Details line that reads:
Details:: turns in 2022

My date math is ignored.

I’ve tested without the Details:: callout - it’s definitely the two nested date() calls.

I can do this with DVJS, I’m just wondering if it’s something that can be done in straight inline DV. And if I’ve got an error or something in my code.

Topic

Summary
  • How to calculate a person’s age?

Input

Summary
```md
# Person Name
Start-Date:: 1980-09-06
Details::
```

Notes

Summary

Q1: What is the data type of this.Start-Date.month(or this.Start-Date.day)?

Summary_Q1

A1:

Another Example: A1_11
```md
month_type = `=typeof(this.Start-Date.month)`
day_type = `=typeof(this.Start-Date.day)`
```
Screenshots: A1_11

month_type = number
day_type = number


Q2: How to transform this.Start-Date.month into MM (or transform this.Start-Date.day into dd)?

Summary_Q2

A2:

Another Example: A2_21
```md
month_MM = `=padleft(string(this.Start-Date.month),2,"0")` 
day_dd = `=padleft(string(this.Start-Date.day),2,"0")`
```
Screenshots: A2_21

month_MM = 09
day_dd = 06


Q3: How to fix the bug in the Inline DQL?

Summary_Q3
Original Example: Q3 (To be modified)
```md
Details:: turns `=date(date(today).year + "-" + this.Start-Date.month + "-" + this.Start-Date.day) - this.Start-Date`  in `=date(today).year`
```

A3:

Another Example: A3_31
```md
Details:: turns `=date(date("today").year + "-" + padleft(string(this.Start-Date.month),2,"0") + "-" + padleft(string(this.Start-Date.day),2,"0")) - this.Start-Date`  in `=date("today").year`
```
Screenshots: A3_31

Details:: turns 42 years in 2022


Q4: How to simplify the Inline DQL(A3_31) when calculating date("2022-09-06")-date("1980-09-06") with skipping the same month and day?

Summary_Q4

A4:

Another Example: A4_41
```md
Details:: turns `=date("today").year - this.Start-Date.year` years in `=date("today").year`
```
Screenshots: A4_41

Details:: turns 42 years in 2022


Q5: How to calculate a person’s age in months and years by using the dur function?

Summary_Q5

A5:

Another Example: A5_51
```md
Details:: turns `=round(dur(date("today") - this.Start-Date).year - 0.5, 0)` years in `=date("today").year`
```
Screenshots: A5_51

Details:: turns 42 years in 2022


1 Like

THANKS!

I debated using the padleft to adjust it, but since my dates worked fine when I didn’t try specifying the year date(today) - this.Start-Date I didn’t think that was an issue.

Of course, A4 is even better, and what I’ll be using.

Thanks again for the QA. My eyes were burning attempting it myself.

1 Like

Hoping some of you DataviewJS veterans can help with this.

I currently have a DataviewJS + Buttons script that creates a button that changes the status variable in the yaml header. That all works great.

---
defer_date: 2022-11-22
status: on-going
---

```dataviewjs 
const {update} = this.app.plugins.plugins["metaedit"].api 
const {createButton} = app.plugins.plugins["buttons"] 
dv.el("p", "Status: `$= dv.current().status`") 
createButton({app, el: this.container, args: {name: "on going"}, clickOverride: {click: update, params: ['status', "on-going", dv.current().file.path]}})
createButton({app, el: this.container, args: {name: "completed"}, clickOverride: {click: update, params: ['status', "completed", dv.current().file.path]}})

Now, I’m trying to create a similar button for adding one day to the defer_date variable. (The idea is to let me push out the start date for certain projects)

However, when I click on the button, it turns the defer_date to just a number 1669122000000 and I don’t know how to change it back to a date.

Can someone help?

---
defer_date: 2022-11-22
---
```dataviewjs 
let d = dv.current().defer_date;
const {update} = this.app.plugins.plugins["metaedit"].api 
const {createButton} = app.plugins.plugins["buttons"] 
dv.el("p", "Defer Date: `$= dv.current().defer_date`") 
createButton({app, el: this.container, args: {name: "+1"}, clickOverride: {click: update, params: ['defer_date', d + 86400000, dv.current().file.path]}})
1 Like