mirror of
				https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
				synced 2025-10-31 09:55:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			106 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| var stringifyNumber = require('../../stringify/stringifyNumber.js');
 | |
| 
 | |
| /** Internal types handle bigint as number, because TS can't figure it out. */
 | |
| function parseSexagesimal(str, asBigInt) {
 | |
|     const sign = str[0];
 | |
|     const parts = sign === '-' || sign === '+' ? str.substring(1) : str;
 | |
|     const num = (n) => asBigInt ? BigInt(n) : Number(n);
 | |
|     const res = parts
 | |
|         .replace(/_/g, '')
 | |
|         .split(':')
 | |
|         .reduce((res, p) => res * num(60) + num(p), num(0));
 | |
|     return (sign === '-' ? num(-1) * res : res);
 | |
| }
 | |
| /**
 | |
|  * hhhh:mm:ss.sss
 | |
|  *
 | |
|  * Internal types handle bigint as number, because TS can't figure it out.
 | |
|  */
 | |
| function stringifySexagesimal(node) {
 | |
|     let { value } = node;
 | |
|     let num = (n) => n;
 | |
|     if (typeof value === 'bigint')
 | |
|         num = n => BigInt(n);
 | |
|     else if (isNaN(value) || !isFinite(value))
 | |
|         return stringifyNumber.stringifyNumber(node);
 | |
|     let sign = '';
 | |
|     if (value < 0) {
 | |
|         sign = '-';
 | |
|         value *= num(-1);
 | |
|     }
 | |
|     const _60 = num(60);
 | |
|     const parts = [value % _60]; // seconds, including ms
 | |
|     if (value < 60) {
 | |
|         parts.unshift(0); // at least one : is required
 | |
|     }
 | |
|     else {
 | |
|         value = (value - parts[0]) / _60;
 | |
|         parts.unshift(value % _60); // minutes
 | |
|         if (value >= 60) {
 | |
|             value = (value - parts[0]) / _60;
 | |
|             parts.unshift(value); // hours
 | |
|         }
 | |
|     }
 | |
|     return (sign +
 | |
|         parts
 | |
|             .map(n => String(n).padStart(2, '0'))
 | |
|             .join(':')
 | |
|             .replace(/000000\d*$/, '') // % 60 may introduce error
 | |
|     );
 | |
| }
 | |
| const intTime = {
 | |
|     identify: value => typeof value === 'bigint' || Number.isInteger(value),
 | |
|     default: true,
 | |
|     tag: 'tag:yaml.org,2002:int',
 | |
|     format: 'TIME',
 | |
|     test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/,
 | |
|     resolve: (str, _onError, { intAsBigInt }) => parseSexagesimal(str, intAsBigInt),
 | |
|     stringify: stringifySexagesimal
 | |
| };
 | |
| const floatTime = {
 | |
|     identify: value => typeof value === 'number',
 | |
|     default: true,
 | |
|     tag: 'tag:yaml.org,2002:float',
 | |
|     format: 'TIME',
 | |
|     test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/,
 | |
|     resolve: str => parseSexagesimal(str, false),
 | |
|     stringify: stringifySexagesimal
 | |
| };
 | |
| const timestamp = {
 | |
|     identify: value => value instanceof Date,
 | |
|     default: true,
 | |
|     tag: 'tag:yaml.org,2002:timestamp',
 | |
|     // If the time zone is omitted, the timestamp is assumed to be specified in UTC. The time part
 | |
|     // may be omitted altogether, resulting in a date format. In such a case, the time part is
 | |
|     // assumed to be 00:00:00Z (start of day, UTC).
 | |
|     test: RegExp('^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})' + // YYYY-Mm-Dd
 | |
|         '(?:' + // time is optional
 | |
|         '(?:t|T|[ \\t]+)' + // t | T | whitespace
 | |
|         '([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)' + // Hh:Mm:Ss(.ss)?
 | |
|         '(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?' + // Z | +5 | -03:30
 | |
|         ')?$'),
 | |
|     resolve(str) {
 | |
|         const match = str.match(timestamp.test);
 | |
|         if (!match)
 | |
|             throw new Error('!!timestamp expects a date, starting with yyyy-mm-dd');
 | |
|         const [, year, month, day, hour, minute, second] = match.map(Number);
 | |
|         const millisec = match[7] ? Number((match[7] + '00').substr(1, 3)) : 0;
 | |
|         let date = Date.UTC(year, month - 1, day, hour || 0, minute || 0, second || 0, millisec);
 | |
|         const tz = match[8];
 | |
|         if (tz && tz !== 'Z') {
 | |
|             let d = parseSexagesimal(tz, false);
 | |
|             if (Math.abs(d) < 30)
 | |
|                 d *= 60;
 | |
|             date -= 60000 * d;
 | |
|         }
 | |
|         return new Date(date);
 | |
|     },
 | |
|     stringify: ({ value }) => value.toISOString().replace(/(T00:00:00)?\.000Z$/, '')
 | |
| };
 | |
| 
 | |
| exports.floatTime = floatTime;
 | |
| exports.intTime = intTime;
 | |
| exports.timestamp = timestamp;
 | 
