# Changes to MfGames Culture => .. Up a Level In the process of updating my website[1], I ended up doing significant amount of work on my arbitrary culture library, mfgames-culture[2]. This was used to let me enter the events and dates in a world-specific formats (such as ‘1454/7/41 MTR 17::61’) and convert them into other formats (including the ISO standard used by the timeline library, vis.js[3]). => /blog/2017/07/16/website-improvements/ 1: /blog/2017/07/16/website-improvements/ => https://gitlab.com/mfgames-culture/ 2: https://gitlab.com/mfgames-culture/ => http://visjs.org/docs/timeline/ 3: http://visjs.org/docs/timeline/ # Why Arbitrary? I can't find the page where I talk about the reason why I'm creating this library, so I'll give a brief run down. In the process of creating world-specific calendars (such as here[4] and here[5]), I don't base all the work off the Gregorian calendar. Instead, I built it up from the ground-up based on the culture, keeping in mind their politics, holy numbers, and other elements. => /blog/2013/09/21/mansupi-tachira-ripochya-solar-calendar/ 4: /blog/2013/09/21/mansupi-tachira-ripochya-solar-calendar/ => /blog/2015/01/01/tarsan-standard-calendar/ 5: /blog/2015/01/01/tarsan-standard-calendar/ This creates a good flavor for the world but makes it difficult to create a good timeline for a novel or the world. Most organization programs don't work outside of Gregorian calendars or formats. That means I have a choice of ignoring my world-specific elements for tracking purposes or find some way of making those in-world calendars to work. That is the crux of mfgames-culture, to create an API and tools for working with arbitrary cultures that are described purely with data files. Eventually, I'll have other versions of this but I'm using the Typescript[6] library as the reference implementation. => https://gitlab.com/mfgames-culture/mfgames-culture-js/ 6: https://gitlab.com/mfgames-culture/mfgames-culture-js/ ## Examples Below are some examples using a command-line program that uses the library. I also have an alias that uses my own culture information. ``` $ sudo npm install --global mfgames-culture-cli $ alias fedran="mfgames-culture --culture=kyo --data=$SRC/fedran-culture-data/dist" ``` ## Parsing Right now, I'm only focusing on dates and times. There are two parts: the structure and the appearance. The structure is the components of the calendar, such as there are twelve months in a year, 28-31 days in a month, one hundred years is called a “century”. The appearance is how those components are formatted, such as the US using `MM/DD/YYYY` but the UK uses `DD/MM/YYYY`. It is the same calendar (structure) but different names for months. The basic idea of the library is to take a JSON[7] or YAML file that describes a calendar and provide an API for using it like many other calendar libraries, such as moment.js[8]. It doesn't many any assumptions of about how many months, days, or even seconds in a day. Instead, everything is calculated based on the file and it produces a rich object that contains that information. => https://gitlab.com/mfgames-culture/mfgames-culture-data/blob/master/data/gregorian.json 7: https://gitlab.com/mfgames-culture/mfgames-culture-data/blob/master/data/gregorian.json => https://momentjs.com/ 8: https://momentjs.com/ ```shell $ mfgames-culture parse 7/7/2017 --indent 2 { "julian": 2457941.5, "type": "instant", "year": 2017, "century": 20, "millenniumCentury": 0, "decade": 201, "centuryDecade": 1, "centuryYear": 17, "decadeYear": 7, "millennium": 2, "yearDay": 187, "yearMonth": 6, "monthDay": 6, "hour24": 0, "meridiem": 0, "hour12": 0, "hourMinute": 0, "minuteSecond": 0 } $ ``` Of course, I need to be able to do the same with my in-world calendar. ```shell $ fedran parse "1454/7/41 MTR 17::61" --no-json --yaml julian: 2383794.0875 type: instant mochyu: 1454 mochyuRote: 317 mochyuRichi: 6 richiRote: 40 koga: 16 mugi: 60 bidashu: 0 $ ``` ## Data Files In both examples, the data files are located somewhere the CLI can find it. In the first case, the files from mfgames-culture-data[9] are packaged with the utility. For the Fedran data, you can find it here[10]. => https://gitlab.com/mfgames-culture/mfgames-culture-data 9: https://gitlab.com/mfgames-culture/mfgames-culture-data => https://gitlab.com/fedran/fedran-culture-data/ 10: https://gitlab.com/fedran/fedran-culture-data/ If you want to download them somewhere, they are just NPM packages. ```shell $ npm install mfgames-culture-data fedran-culture-data $ ls node_modules/mfgames-culture-data/dist/ combined.json duodecimal-period.json gregorian.json combined.min.json duodecimal-period.min.json gregorian.min.json duodecimal.json en-US.json index.json duodecimal.min.json en-US.min.json index.min.json $ ls node_modules/fedran-culture-data/dist/ combined.json mifuno-kopachi-period.json combined.min.json mifuno-kopachi-period.min.json index.json natural.json index.min.json natural.min.json kyo.json seasons.json kyo.min.json seasons.min.json mansupi-tachira-ripochya.json tar.json mansupi-tachira-ripochya.min.json tar.min.json mifuno-kopachi.json tarsan-standard-calendar.json mifuno-kopachi.min.json tarsan-standard-calendar.min.json $ ``` If you are curious why I have the data files as npm packages, I decided to make it easier to version them so the website won't break until I'm ready to upload it. Not to mention, semantic versions[11] is useful for more than libraries. => http://semver.org/ 11: http://semver.org/ ## Calendars I'm not going to go into too much directions of how to create the format. I have decent documentation[12] on the purpose and setup. => https://gitlab.com/mfgames-culture/mfgames-culture-data/blob/master/docs/index.md 12: https://gitlab.com/mfgames-culture/mfgames-culture-data/blob/master/docs/index.md The main part is a calendar consists of cycles. For example, the Gregorian is based on a year. A month is calculated from days within a year and decades are a formula based on decades. The system recursively goes through these cycles to figure out the individual amounts that you saw above. ## Cultures Cultures are where dates (instants) and periods (durations) are formatted. A culture has many ways of formatting any given instant, once you have one, you can pull it out in a variety of ways. ```shell $ mfgames-culture format "2017-07-14 23:19:04" --output-style markdown-table | format | results | | --------------------- | ---------------------------- | | JD | 2457949.47157407407407407407 | | M/D/YYYY | 7/14/2017 | | M/D/YYYY h:mm tt | 7/14/2017 11:19 PM | | MM/DD/YYYY | 07/14/2017 | | MM/DD/YYYY h:mm:ss tt | 07/14/2017 11:19:04 PM | | MMM DD, YY | Jul 14, 17 | | YYYY-MM-DD | 2017-07-14 | | YYYY-MM-DD HH:mm:ss | 2017-07-14 23:19:04 | | default | 7/14/2017 11:19 PM | | h:mm tt | 11:19 PM | | shortDate | 7/14/2017 | | shortDateTime | 7/14/2017 11:19 PM | | shortTime | 11:19 PM | $ mfgames-culture format "2017-07-14 23:19:04" --output-format shortDateTime 7/14/2017 11:19 PM $ ``` Again, this can be done with my fantasy calendar also. ```shell $ fedran format "1454/7/41 MTR 17::61" --output-style markdown-table | format | results | | ------------------- | ---------------------- | | JD | 2383794.0875 | | YYYY | 1454 | | YYYY MTR | 1454 MTR | | YYYY/OOO | 1454/318 | | YYYY/OOO K:: | 1454/318 17:: | | YYYY/OOO K::M | 1454/318 17::61 | | YYYY/OOO K::M:B | 1454/318 17::61:1 | | YYYY/OOO MTR | 1454/318 MTR | | YYYY/OOO MTR K:: | 1454/318 MTR 17:: | | YYYY/OOO MTR K::M | 1454/318 MTR 17::61 | | YYYY/OOO MTR K::M:B | 1454/318 MTR 17::61:1 | | YYYY/R | 1454/7 | | YYYY/R MTR | 1454/7 MTR | | YYYY/R/O | 1454/7/41 | | YYYY/R/O K:: | 1454/7/41 17:: | | YYYY/R/O K::M | 1454/7/41 17::61 | | YYYY/R/O K::M:B | 1454/7/41 17::61:1 | | YYYY/R/O MTR | 1454/7/41 MTR | | YYYY/R/O MTR K:: | 1454/7/41 MTR 17:: | | YYYY/R/O MTR K::M | 1454/7/41 MTR 17::61 | | YYYY/R/O MTR K::M:B | 1454/7/41 MTR 17::61:1 | | default | 1454/7/41 17::61 | | shortDate | 1454/7/41 | | shortDateTime | 1454/7/41 17::61 | | shortTime | 17::61 | $ fedran format "1454/7/41 MTR 17::61" --output-format shortDateTime 1454/7/41 17::61 $ ``` ## Typescript/Javascript These libraries can also be used directly. This is how I implemented the timeline[13] on my website. It is also used by the build process to create the date/time tooltips like you can see on Rutejìmo's[14] page. => https://fedran.com/timeline/ 13: https://fedran.com/timeline/ => https://fedran.com/rutejimo/ 14: https://fedran.com/rutejimo/ The first part is to load a culture. ```typescript import * as mfgamesCulture from "mfgames-culture"; import * as mfgamesCultureData from "mfgames-culture-data"; // Create a data provider for the basic culture data. The entire JSON files is // exported as `.combined` which is passed into the property provider. var provider = new mfgamesCulture.PropertyCultureDataProvider( mfgamesCultureData.combined ); var cultureData = provider.getCultureSync("en-US"); var culture = new mfgamesCulture.Culture(cultureData); ``` (There is a promise version in `getCulturePromise`). Once a culture is loaded, it can be used to create an in-memory representation of a format described in the culture file. A single point in time is called an `instant` and a range of time is called a `period`. ```typescript var instant = culture.parseInstant("2015-01-02 13:14:15"); console.log(instant); ``` This produces an output of: ```json { julian: { [String: '2457025.0515625'] s: 1, e: 6, c: [ 2, 4, 5, 7, 0, 2, 5, 0, 5, 1, 5, 6, 2, 5 ], constructor: { [Function: Big] DP: 20, RM: 1, E_NEG: -7, E_POS: 21 } }, type: 'instant', year: 2015, century: 20, millenniumCentury: 0, decade: 201, centuryDecade: 1, centuryYear: 15, decadeYear: 5, millennium: 2, yearDay: 1, yearMonth: 0, monthDay: 1, hour24: 13, meridiem: 1, hour12: 1, hourMinute: 14, minuteSecond: 15 } ``` It can also be used to format results. ```typescript var format = culture.formatInstant(instant, "YYYY-MM-DD HH:mm:ss"); console.log(format); ``` ... which produces: ``` 2015-01-02 13:14:15 ``` To get the timeline page, I basically parse the in-world dates, convert them to Julian Dates (using the `JD` format), then use that number to figure out the ISO date and time. Then I override the labels to take the Gregorian date and convert it back to the in-world dates so the reader never sees how I use Gregorian as the intermediary format. This is why I also have every instant also figure out an effective Julian Date. That way, I can convert between any instant, even between multiple cultures. # Metadata Categories: => /categories/programming/ Programming Tags: => /tags/fedran/ Fedran => /tags/mfgames-culture/ mfgames-culture => /tags/mfgames-culture-js/ mfgames-culture-js # Footer Below are various useful links within this site and to related sites (not all have been converted over to Gemini). => /now/ Now => /contact/ Contact => /bio/ Biography => /bibliography/ Bibliography => /support/ Support => /fiction/ Fiction => //fedran.com/ Fedran => https://mfgames.com/ Coding => https://moonfire.us/ The Moonfires => /categories/ Categories => /tags/ Tags => /privacy/ Privacy => /colophon/ Colophon => /license/ License => https://lists.typewriter.press/subscription?f=RDQ6f3AFHXnX2o763d5TgUmaYP7N763gR6FjZyGUUFWhyRkpgZF9I35ySICDBEdFFtgG Mailing List => https://d.moonfire.us/blog/2017/07/17/mfgames-culture/