├── README.md ├── dateformat.js └── screenshot.jpg /README.md: -------------------------------------------------------------------------------- 1 | # sparkar-dateformat 2 | > Patch script for date formatting for Spark AR Studio. 3 | 4 | ![Screenshot](./screenshot.jpg) 5 | 6 | ## Install 7 | [Click here](https://github.com/nikolvs/sparkar-dateformat/archive/main.zip) to download the zip file, extract it and import `dateformat.js` as an asset for your Spark AR project. 8 | 9 | ## Usage 10 | Below are the patch inputs/outputs you have to define for the script. 11 | 12 | ### From Script 13 | 14 | #### `date` 15 | * **Description**: Formatted date you receive from the script. 16 | * **Type**: Text 17 | 18 | ### To Script 19 | 20 | #### `format` 21 | * **Description**: Set in which format pattern the date text will be generated. 22 | * **Type**: Text 23 | * **Optional**: `true` 24 | * **Default**: `'YYYY-MM-DD HH:mm:ss'` 25 | 26 | **Patterns** 27 | | Input | Example | Description 28 | | --- | --- | --- 29 | | `YYYY` | `2021` | 4 digit year. 30 | | `YY` | `21` | 2 digit year. 31 | | `MM` | `02` | Month number from 01 to 12 (with leading zero). 32 | | `M` | `2` | Month number from 1 to 12. 33 | | `DD` | `09` | Day of month from 01 to 31 (with leading zero). 34 | | `D` | `9` | Day of month from 1 to 31. 35 | | `HH` | `06` | Hours (24 hour time) from 00 to 23 (with leading zero). 36 | | `H` | `6` | Hours (24 hour time) from 0 to 23. 37 | | `hh` | `03` | Hours (12 hour time) from 01 to 12 (with leading zero). 38 | | `h` | `3` | Hours (12 hour time) from 1 to 12. 39 | | `mm` | `04` | Minutes from 00 to 59 (with leading zero). 40 | | `m` | `4` | Minutes from 0 to 59. 41 | | `ss` | `07` | Seconds from 00 to 59 (with leading zero). 42 | | `s` | `7` | Seconds from 0 to 59. 43 | | `A` | `PM` | Post or ante meridiem in uppercase. 44 | | `a` | `am` | Post or ante meridiem in lowercase. 45 | 46 | #### `refreshInterval` 47 | * **Description**: Interval in seconds in which the date text will be refreshed. 48 | * **Type**: Number 49 | * **Optional**: `true` 50 | * **Default**: `1` 51 | 52 | #### `debug` 53 | * **Description**: Display debug messages on console. 54 | * **Type**: Boolean 55 | * **Optional**: `true` 56 | * **Default**: `false` 57 | 58 | ## Credits 59 | * [Josh Beckwith](https://github.com/positlabs) for making [spark-localtime](https://github.com/positlabs/spark-localtime), which inspired me to create this script. I originally planned to contribute to his repo, but since his script relied on the `toLocaleDateString` method and it doesn't seen to work on Spark AR Studio anymore, I just made my own script from scratch; 60 | * [Taynara Lima](https://www.instagram.com/taynaragpyk/) for creating Instagram filters, which made me see the limitations of Spark AR Studio in relation to date formats and inspired me to help her. -------------------------------------------------------------------------------- /dateformat.js: -------------------------------------------------------------------------------- 1 | const Diagnostics = require('Diagnostics'); 2 | const Patches = require('Patches'); 3 | const Time = require('Time'); 4 | 5 | /** 6 | * Global variables. 7 | */ 8 | const globals = { 9 | interval: null, 10 | }; 11 | 12 | /** 13 | * Script options. 14 | */ 15 | const options = { 16 | /** 17 | * Default date format. 18 | */ 19 | format: 'YYYY-MM-DD HH:mm:ss', 20 | 21 | /** 22 | * Default date refresh interval in seconds. 23 | */ 24 | refreshInterval: 1, 25 | 26 | /** 27 | * Display debug info. 28 | */ 29 | debug: false, 30 | }; 31 | 32 | /** 33 | * Display debug messages on console. 34 | * 35 | * @param {String} context 36 | * @param {String} message 37 | */ 38 | const debug = (context, message) => { 39 | options.debug && Diagnostics.log(`[debug][${context}] ${message}`); 40 | }; 41 | 42 | /** 43 | * Update patch input values. 44 | */ 45 | const update = async () => { 46 | try { 47 | const dateString = formatDate(new Date(), options.format); 48 | await Patches.inputs.setString('date', dateString); 49 | debug('from script', `date: ${dateString}`); 50 | } catch (err) { 51 | Diagnostics.log(err); 52 | } 53 | }; 54 | 55 | /** 56 | * Returns a date/time number in two digits format. 57 | * 58 | * @param {Number} date 59 | * @returns {String} 60 | */ 61 | const twoDigit = (date) => String(date).padStart(2, '0'); 62 | 63 | /** 64 | * Return hours from date to 12 hours format. 65 | * 66 | * @param {Date} date 67 | * @returns {Number} 68 | */ 69 | const twelveHoursFormat = (date) => (date.getHours() % 12) || 12; 70 | 71 | /** 72 | * Format a date according to the input string. 73 | * 74 | * @param {Date} date 75 | * @param {String} format 76 | */ 77 | const formatDate = (date, format) => { 78 | return format 79 | .replace(/(YYYY)/g, date.getFullYear()) 80 | .replace(/(YY)/g, String(date.getFullYear()).slice(-2)) 81 | .replace(/(MM)/g, twoDigit(date.getMonth() + 1)) 82 | .replace(/(M)/g, date.getMonth() + 1) 83 | .replace(/(DD)/g, twoDigit(date.getDate())) 84 | .replace(/(D)/g, date.getDate()) 85 | .replace(/(HH)/g, twoDigit(date.getHours())) 86 | .replace(/(H)/g, date.getHours()) 87 | .replace(/(hh)/g, twoDigit(twelveHoursFormat(date))) 88 | .replace(/(h)/g, twelveHoursFormat(date)) 89 | .replace(/(mm)/g, twoDigit(date.getMinutes())) 90 | .replace(/(m)/g, date.getMinutes()) 91 | .replace(/(ss)/g, twoDigit(date.getSeconds())) 92 | .replace(/(s)/g, date.getSeconds()) 93 | .replace(/(A)/g, date.getHours() >= 12 ? 'PM': 'AM') 94 | .replace(/(a)/g, date.getHours() >= 12 ? 'pm' : 'am'); 95 | }; 96 | 97 | /** 98 | * Patch output types mapped to monitor functions names. 99 | */ 100 | const outputTypes = { 101 | 'string': 'getStringOrFallback', 102 | 'number': 'getScalarOrFallback', 103 | 'boolean': 'getBooleanOrFallback', 104 | }; 105 | 106 | /** 107 | * Watch a patch output parameter. 108 | * 109 | * @param {String} name 110 | * @param {String} type 111 | * @param {Function} callback 112 | */ 113 | const watchOutput = async (name, type, callback) => { 114 | const getOutputWatcher = Patches.outputs[outputTypes[type]]; 115 | const watcher = await getOutputWatcher(name, options[name]); 116 | 117 | return watcher.monitor({ fireOnInitialValue: true }).subscribe(({ newValue }) => { 118 | debug('to script', `${name}: ${newValue}`); 119 | callback(newValue); 120 | }); 121 | }; 122 | 123 | /** 124 | * Main function. 125 | */ 126 | const main = async () => { 127 | try { 128 | // Update refresh interval. 129 | watchOutput('refreshInterval', 'number', (refreshInterval) => { 130 | if (globals.interval) { 131 | Time.clearInterval(globals.interval); 132 | } 133 | 134 | options.refreshInterval = refreshInterval; 135 | globals.interval = Time.setInterval(update, refreshInterval * 1000); 136 | }); 137 | 138 | // Update date format. 139 | watchOutput('format', 'string', (format) => { 140 | options.format = format; 141 | }); 142 | 143 | // Update debug option. 144 | watchOutput('debug', 'boolean', (debug) => { 145 | options.debug = debug; 146 | }); 147 | } catch (err) { 148 | Diagnostics.log(err); 149 | } 150 | }; 151 | 152 | main(); 153 | -------------------------------------------------------------------------------- /screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nikolvs/sparkar-dateformat/30e5536da91c15e7b6ae8167a3c08b1e2a9299ad/screenshot.jpg --------------------------------------------------------------------------------