All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.xfa.ut.DateTimeUtil Maven / Gradle / Ivy

There is a newer version: 2024.11.18751.20241128T090041Z-241100
Show newest version
/*
 * ADOBE CONFIDENTIAL
 *
 * Copyright 2005 Adobe Systems Incorporated All Rights Reserved.
 *
 * NOTICE: All information contained herein is, and remains the property of
 * Adobe Systems Incorporated and its suppliers, if any. The intellectual and
 * technical concepts contained herein are proprietary to Adobe Systems
 * Incorporated and its suppliers and may be covered by U.S. and Foreign
 * Patents, patents in process, and are protected by trade secret or copyright
 * law. Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained from
 * Adobe Systems Incorporated.
 */

package com.adobe.xfa.ut;

/**
 * This class implements static utility methods used by the LcDate and LcTime classes.
 *
 * @exclude from published api -- Mike Tardif, May 2006.
 */

public final class DateTimeUtil {

	/*
	 * Disallow instances of this class
	 */
	private DateTimeUtil() {
		// empty
	}

	/**
	 * Table of Kanji ideographic numeric characters
	 * as used in Japanese and Simplified Chinese locales.
	 */
	static final char Kanji_Num[] = {
		/* 0 */		'\u3007',	
		/* 1 */		'\u4E00',	
		/* 2 */		'\u4E8C',	
		/* 3 */		'\u4E09',	
		/* 4 */		'\u56DB',	
		/* 5 */		'\u4E94',	
		/* 6 */		'\u516D',	
		/* 7 */		'\u4E03',	
		/* 8 */		'\u516B',	
		/* 9 */		'\u4E5D',	
		/* 10 */	'\u5341',	
		/* 100 */	'\u767E',	
		/* 1000 */	'\u5343'
	};
	
	/**
	 * Table of Hanja ideographic numeric characters
	 * as used in Korean and Traditional Chinese locales.
	 */
	static final char Hanja_Num[] = {
		/* 0 */		'\u96F6',	// Watson 1213930 prevents us from using U+F9B2.	  
		/* 1 */		'\u4E00',	
		/* 2 */		'\u4E8C',	
		/* 3 */		'\u4E09',	
		/* 4 */		'\u56DB',	
		/* 5 */		'\u4E94',	
		/* 6 */		'\u516D',	
		/* 7 */		'\u4E03',	
		/* 8 */		'\u516B',	
		/* 9 */		'\u4E5D',	
		/* 10 */	'\u5341',	
		/* 100 */	'\u767E',	
		/* 1000 */	'\u5343'
	};

	/**
	 * Table of Hangul ideographic numeric characters
	 * as used in Korean locales.
	 */
	static final char Hangul_Num[] = {
		/* 0 */		'\uC601',	
		/* 1 */		'\uC77C',	
		/* 2 */		'\uC774',	
		/* 3 */		'\uC0BC',	
		/* 4 */		'\uC0AC',	
		/* 5 */		'\uC624',	
		/* 6 */		'\uC721',	
		/* 7 */		'\uCE60',	
		/* 8 */		'\uD314',	
		/* 9 */		'\uAD6C',	
		/* 10 */	'\uC2ED',	
		/* 100 */	'\uBC31',	
		/* 1000 */	'\uCC9C'
	};

	/*
	 * Get a (previously matched) number of digits from a given start
	 * position to a given end position of the given string.
	 *
	 * @param src the string to parse.
	 * @param begPos the beginning parsing position within the string.
	 * @param endPos the ending parsing position within the string.
	 * @param fw get using fullwidth (instead of ASCII) digits when true.
	 * @param zero the native zero digit.
	 *
	 * @return the integral value of the number of digits matched.
	 */
	static int getNum(String src, int begPos, int endPos,
													boolean fw, char zero) {
		assert(begPos < endPos);
		int n = 0;
		while (begPos < endPos && begPos < src.length()) {
			char chr = src.charAt(begPos++);
			n *= 10;
			if (fw)
				n += chr - 0xFF10;
			else
				n += chr - zero;
		}
		return n;
	}

	/*
	 * Get a number using the given table of ideographic numeric characters
	 * from a given start position to a given end position of the given string
	 * in accordance to (or not) ten's rules.
	 *
	 * @param src the string to parse.
	 * @param begPos the beginning parsing position within the string.
	 * @param endPos the ending parsing position within the string.
	 * @param num the table of ideographic numbers.
	 * @param tr get using ten's rule when true.
	 *
	 * @return the integral value of the number of digits matched.
	 */
	static int getNum(String src, int begPos, int endPos,
											char num[], boolean tr) {
		assert(begPos < endPos);
		int n = 0;
		if (tr) { // w/ ten's rule.
			int mils = 0, cens = 0, tens = 0, ones = 0;
			while (begPos < endPos && begPos < src.length()) {
				char chr = src.charAt(begPos++);
				for (int p = 0; p < num.length; p++) {
					if (chr == num[p]) {
						if (p == 12) { // thousand
							mils = ones > 0 ? ones : 1;
							ones = 0;
						}
						else if (p == 11) { // hundred
							cens = ones > 0 ? ones : 1;
							ones = 0;
						}
						else if (p == 10) { // ten
							tens = ones > 0 ? ones : 1;
							ones = 0;
						}
						else if (p <= 9) { // ones
							ones = p;
						}
						break;
					}
				}
			}
			n = mils * 1000 + cens * 100 + tens * 10 + ones;
		}
		else { // w/o ten's rule.
			while (begPos < endPos && begPos < src.length()) {
				char chr = src.charAt(begPos++);
				int p = 0;
				for (; p < num.length; p++) {
					if (chr == num[p] && p <= 9) {
						n *= 10;
						n += p;
						break;
					}
				}
				if (p == num.length)
					break;
			}
		}
		return n;
	}

	/**
	 * Format a given number into a given string of given width.  This is the
	 * equivalent of printf("%.d", w, n)
	 *
	 * @param w the width of string.
	 * @param n the number to format.
	 * @param fw format using fullwidth (instead of ASCII) digits when true.
	 * @param zero the native zero digit.
	 *
	 * @return  the formatted string.
	 */
	static String fmtNum(int w, int n, boolean fw, char zero) {
	    assert(n >= 0 && w > 0);
		StringBuilder s = new StringBuilder();
	    for (int i = w - 1; i >= 0; i--) {
	        char d = (char)(zero + n % 10);
			if (fw)
				d += 0xFEE0;
	        s.insert(0, d);
	        n /= 10;
	    }
	    return s.toString();
	}
	
	/*
	 * Format a given number into a given string of given width,
	 * using the given table of ideographic numeric characters
	 * in accordance to (or not) ten's rules.
	 * Ten's rules is described at Wikipedia under Chinese numerals,
	 * Japanese numerals and Korean numerals.
	 *
	 * @param d the number of digits to format.
	 * @param n the number to format.
	 * @param num the table of ideographic numbers.
	 * @param tr format using ten's rule digits when set:
	 *	1 for Chinese rules and
	 *	-1 for Japanese rules.
	 *
	 * @return the formatted string.
	 */
	static String fmtNum(int d, int n, char num[], int tr) {
		StringBuilder s = new StringBuilder();
		if (num == null)
			return "";
	    assert(n >= 0 && 1 <= d && d <= 4);
		int mils = n / 1000;
		int cens = (n - mils * 1000) / 100;
		int tens = (n - mils * 1000 - cens * 100) / 10;
		int ones = (n - mils * 1000 - cens * 100 - tens * 10);
		if (tr != 0) { // w/ ten's rule.
			boolean prevIsZero = false;
			if (mils > 0) {
				if (tr > 0 || mils > 1)
					s.append(num[mils]);
				s.append(num[12]);
			}
			if (cens > 0) {
				if (tr > 0 || cens > 1)
					s.append(num[cens]);
				s.append(num[11]);
			}
			else if (tr > 0) {
				if (! prevIsZero && tens > 0 && ones > 0 && !StringUtils.isEmpty(s)) {
					s.append(num[0]);
					prevIsZero = true;
				}
			}
			if (tens > 0) {
				if (tens > 1)
					s.append(num[tens]);
				s.append(num[10]);
			}
			else if (tr > 0) {
				if (! prevIsZero && ones > 0 && !StringUtils.isEmpty(s)) {
					s.append(num[0]);
					prevIsZero = true;
				}
			}
			if (StringUtils.isEmpty(s) || ones > 0)
				s.append(num[ones]);
		}
		else { // w/o ten's rule.
			if (mils > 0)
				s.append(num[mils]);
			if (s.length() > 0 || cens > 0)
				s.append(num[cens]);
			if (s.length() > 0 || tens > 0)
				s.append(num[tens]);
			s.append(num[ones]);
		}
	    return s.toString();
	}
	
	/*
	 * Format a given number into a given string of given maximal width.
	 * This is the equivalent of printf("%d", n)
	 *
	 * @param w the maximal width of string.
	 * @param n the number to format.
	 * @param fw format using fullwidth (instead of ASCII) digits when true.
	 * @param zero the native zero digit.
	 *
	 * @return the formatted string.
	 */
	static String fmtPlainNum(int w, int n, boolean fw, char zero) {
	    assert (n >= 0 && w > 0);
		StringBuilder s = new StringBuilder();
	    for (int i = w - 1; i >= 0; i--) {
	        char d = (char)(zero + n % 10);
			if (fw)
				d += 0xFEE0;
			s.insert(0, d);
	        n /= 10;
	        if (n == 0)
	            break;
	    }
	    return s.toString();
	}
	/*
	 * Format a given string using fullwidth characters.
	 *
	 * @param src the source string.
	 * @param fw format using fullwidth characters when true.
	 *
	 * @return the formatted string.
	 */
	static String fmtStr(String src, boolean fw /* =false */) {
		StringBuilder s = new StringBuilder();
	    for (int i = 0, n = src.length(); i < n; i++)
			s.append(matchChr(src.charAt(i), fw));
		return s.toString();
	}


	/*
	 * Match a name at a given position of the given string from
	 * a list of given names.
	 * Perform a case insensitive search for the best match.
	 *
	 * @param src the string to match.
	 * @param srcPos the starting position within the string.
	 * @param names the array of the names to match from.
	 * @param is do case insensitive search for the best match when true.
	 *
	 * @return the index within names that was matched, and -1 otherwise.
	 */
	static int matchName(String src, int srcPos,
										String[] names, boolean is) {
		//
		// There may be multiple strings in the names[] array which have
		// the same prefix, so we keep track of the longest match, and
		// return that.  This requires us to check all array elements.
		//
		int matchIdx = -1;
		int matchLen = -1;
		String pSrc = src.substring(srcPos);
		for (int i = 0; i < names.length; i++) {
			//
			// Always check if we have no match yet; otherwise
			// only compare potentially longer matches.
			//
			if (names[i] == null)
				continue;
			int len = names[i].length();
			if (len <= matchLen)
				continue;
			else if (len == 0 || pSrc.startsWith(names[i])) {
				matchIdx = i;
				matchLen = len;
			}
		}
		return matchIdx;
	}

	/*
	 * Match a number using the given table of ideographic numeric
	 * characters from a given start position to a given end position
	 * of the given string.
	 *
	 * @param src the string to match.
	 * @param begPos the beginning parsing position within the string.
	 * @param endPos the ending parsing position within the string.
	 * @param num the table of ideographic numbers.
	 * @param tr match using ten's rule digits when true.
	 *
	 * @return the number of digits matched, or -1 otherwise.
	 */
	static int matchNum(String src, int begPos, int endPos,
													char num[], boolean tr) {
		if (num == null)
			return -1;
		assert(begPos < endPos);
		int srcLen = src.length();
		int nDigitsSeen = 0;
		if (tr) { // w/ ten's rule.
			int mils = 0, cens = 0, tens = 0, ones = 1;
			while (begPos < srcLen) {
				char chr = src.charAt(begPos++);
				if (chr == '\u5143')
					return (nDigitsSeen > 0) ? nDigitsSeen : 1;
				int p = 0;
				for (; p < num.length; p++) {
					if (chr == num[p]) {
						if (p == 12) { // thousands
							if (mils > 0 || cens > 0 || tens > 0)
								return (nDigitsSeen > 0) ? nDigitsSeen : -1;
							mils = ones; ones = 1;
						}
						else if (p == 11) { // hundreds
							if (cens > 0 || tens > 0)
								return (nDigitsSeen > 0) ? nDigitsSeen : -1;
							cens = ones; ones = 1;
						}
						else if (p == 10) { // tens
							if (tens > 0)
								return (nDigitsSeen > 0) ? nDigitsSeen : -1;
							tens = ones; ones = 1;
						}
						else if (p <= 9) { // ones
							if (ones != 1)
								return (nDigitsSeen > 0) ? nDigitsSeen : -1;
							ones = p;
						}
						nDigitsSeen++;
						break;
					}
				}
				if (p == num.length)
					break;
			}
		}
		else { // w/o ten's rule.
    		int end = begPos;
    		for (int beg = begPos; beg < endPos; beg++) {
    			if (end < src.length())
        			end++;
    		}
            endPos = end;
			while (begPos < endPos /* && begPos < src.length() */) {
				char chr = src.charAt(begPos++);
				if (chr == '\u5143')
					return (nDigitsSeen > 0) ? nDigitsSeen : 1;
				int p = 0;
				for (; p <= 9; p++) {
					if (chr == num[p]) {
						nDigitsSeen++;
						break;
					}
				}
				if (p == 10)
					break;
			}
		}
		return (nDigitsSeen > 0) ? nDigitsSeen : -1;
	}


	/*
	 * Match a number of digits from a given start position
	 * to a given end position of the given string.
	 *
	 * @param src the string to match.
	 * @param begPos the beginning parsing position within the string.
	 * @param endPos the ending parsing position within the string.
	 * @param fw use fullwidth (instead of ASCII) digits when true.
	 * @param zero the native zero digit.
	 *
	 * @return the number of digits matched, or -1 otherwise.
	 */
	static int matchNum(String src, int begPos, int endPos,
												boolean fw, char zero) {
		assert(begPos < endPos);
		int nDigitsSeen = 0;
		int end = begPos;
		for (int beg = begPos; beg < endPos; beg++) {
			if (end < src.length())
    			end++;
		}
        endPos = end;
		while (begPos < endPos && begPos < src.length()) {
			char chr = src.charAt(begPos++);
			if (! fw && (zero > chr || chr > zero + 9))
				break;
			if (fw && (0xFF10 > chr || chr > 0xFF19))
				break;
			nDigitsSeen++;
		}
		return (nDigitsSeen > 0) ? nDigitsSeen : -1;
	}


	/*
	 * Match a given string from the given start position
	 * of the given source string.  The matching can be made
	 * fullwidth sensitive.
	 *
	 * @param src the source string to match.
	 * @param srcPos the beginning matching position within the source string.
	 * @param str the string to look for.
	 * @param fw use fullwidth (instead of ASCII) matching when true.
	 *
	 * @return the number of digits matched, or -1 otherwise.
	 */
	static int matchStr(String src, int srcPos, String str, boolean fw) {
		for (int i = 0, n = str.length(); i < n; ) {
			char chr = (srcPos < src.length()) ? src.charAt(srcPos++) : 0;
			if (fw) {
				if (0xFF01 <= chr && chr <= 0xFF5E) {
					chr -= 0xFFE0;
					chr &= 0x00FF;
				}
				else if (chr == 0x3000) {
					chr = ' ';
				}
			}
			if (str.charAt(i++) != chr)
				return -1;
		}
		return srcPos;
	}


	/*
	 * Increment the position given a Unicode character increment 
	 * along the given start position of a given string.
	 *
	 * @param src the source string.
	 * @param srcPos the starting position within the source string.
	 * @param inc the Unicode character increment.
	 *
	 * @return the incremented byte position within the string.
	 */
	static int incPos(String src, int srcPos, int inc) {
		assert(inc > 0);
		for (int i = 0; i < inc; i++)
			src.charAt(srcPos++);
		return srcPos;
	}

	/*
	 * Match a given string to a given Unicode character.
	 * The match is fullwidth character insensitive!
	 *
	 * @param src the string to search.
	 * @param chr the Unicode character to find.
	 * @return boolean true if found, and false otherwise.
	 */
	static boolean matchChr(String src, char chr) {
		if (0xFF01 <= chr && chr <= 0xFF5E) {
			chr -= 0xFFE0;
			chr &= 0x00FF;
		}
		else if (chr == 0x3000) {
			chr = ' ';
		}
	    for (int i = 0, n = src.length(); i < n; i++)
			if (src.charAt(i) == chr)
				return true;
	    return false;
	}

	/*
	 * Return a (fullwidth) Unicode character.
	 *
	 * @param chr the ASCII character to return.
	 * @param fw use fullwidth (instead of ASCII) characters when true.
	 *
	 * @return the character to matched.
	 */
	static char matchChr(char chr, boolean fw) {
		if (fw) {
			if (0x0021 <= chr && chr <= 0x007E)
				chr += 0xFEE0;
			else if (chr == ' ')
				chr = 0x3000;
		}
		return chr;
	}


	/*
	 * Match a given string at a given position to a given Unicode character.
	 * The match is fullwidth character sensitive!
	 *
	 * @param src the string to search.
	 * @param srcPos the starting position within the string.
	 * @param chr the Unicode character to find.
	 * @param fw use fullwidth (instead of ASCII) characters when true.
	 * @return Boolean true if matched, and false otherwise.
	 */
	static boolean matchChr(String src, int srcPos,
														char chr, boolean fw) {
		if (srcPos >= src.length())
			return false;
		return (matchChr(src.charAt(srcPos), fw) == chr);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy