de.frame4j.util
Class TimeHelper
java.lang.Object
de.frame4j.util.TimeHelper
@MinDoc(copyright="Copyright 2000 - 2004, 2009 A. Weinert",
author="Albrecht Weinert",
version="V.37",
lastModified="10.04.2010",
lastModifiedBy="A. Weinert",
usage="import TimeHelper to your classes or\n\n java de.frame4j.util.TimeHelper [options] [time [time .. [loop]",
purpose="common time and date utilities and constants, parser")
public abstract class TimeHelper- extends Object
Methods and (final) values for time / date handling.
This class features some methods — partly very powerful — for
time and calendar tasks, as well as some relevant values.
The classes implementing the interface ConstTime rely
on this class.
©
Copyright 2000 - 2004, 2009 Albrecht Weinert
- See Also:
ComVar,
TimeRO,
ConstTime,
ModifTime
|
Field Summary |
static Action |
ACTION_TZ0
Action for time zone offset 0 , UTC. |
static int |
CET_BASIC_OFFSET
(Base-) offset in minutes of time zone CET / MEZ to UTC . |
static int |
DAYSin4YEARS
Days in four years (implying one of it being a leap year). |
static int |
EU_END_MONTH
Ending month for summer time in EU (October = 10). |
static int |
EU_START_MONTH
Starting month for summer time in EU (March = 3). |
static int |
EU_START_YEAR
First year to apply EU summer time rules. |
static int |
EU_SWITCH_HOUR
Start- and and hour for summer time in EU (02:00).
Remark: At the end of summer time, the politicians did not choose to
prolong the end of Saturday having 24:00:00.000 to 24:59:59.000 as an
uniquely numbered extra time of day.
The choice of using Sunday 02:00:00 instead, gives us the time
02:00:00.000 to 02:59:59.000 twice. |
static int |
EU_SWITCH_WEEKDAY
Start and end day of week for summer time in EU (Sunday = 0). |
static ThreadLocal<ModifTime> |
helpTimeHolder
Time object for helpers. |
static Action[] |
RATE_CHOOSE
Action list for duration or rates. |
static Action[] |
TIME_CHOOSE
Action list for date and time of day. |
|
Method Summary |
static StringBuilder |
appendDuration(StringBuilder bastel,
long dur)
Format a duration or rate. |
static int |
daysSince1Mrz68(int d,
int m,
int j)
Calculate the days since 1 March 1968 .
|
static Appendable |
displTimeZones(StringBuilder bastel)
Generate a display of all pre-fabricated time zones. |
static String |
formatSQL(long time)
Formatting of date and time in SQL format. |
static boolean |
haveSameRules(TimeZone a,
TimeZone b)
Do two time zones have the same rules. |
static boolean |
isLeapYear(int y)
Leap year. |
static long |
javaTimetoMS(long javaTime)
Transform Java time (long, ms to Microsoft time stamp (long, ns). |
static void |
main(String[] args)
Display some info about class, time zones, explore the parser etc. |
static long |
msToJavaTime(long msTimeStamp)
Transform Microsoft time stamp (long, ns) to Java time (long, ms). |
static long |
parse(CharSequence time)
Get / parse a time from String representation. |
static long |
parse(CharSequence time,
boolean endDay)
Get / parse a time from String representation. |
static long |
parseDuration(CharSequence rate)
Parsing a rate (or duration). |
| Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
CET_BASIC_OFFSET
public static final int CET_BASIC_OFFSET
- (Base-) offset in minutes of time zone CET / MEZ to UTC .
Adding this offset multiplied by 60000 to the absolute time in ms
gives an absolute local time (in ms). The value for CET (MEZ) is
+60 (meaning +1 hour). This holds for standard or winter time.
Value: 60
- See Also:
- Constant Field Values
EU_START_YEAR
public static final int EU_START_YEAR
- First year to apply EU summer time rules.
Since 1980 all European Union countries (+ some others) obey to unified
daylight saving time rules. They can be described by five parameters.
Value: 1980
- See Also:
EU_START_MONTH,
EU_END_MONTH,
EU_SWITCH_WEEKDAY,
EU_SWITCH_HOUR,
Constant Field Values
EU_START_MONTH
public static final int EU_START_MONTH
- Starting month for summer time in EU (March = 3).
Value: 3
- See Also:
EU_START_YEAR,
Constant Field Values
EU_END_MONTH
public static final int EU_END_MONTH
- Ending month for summer time in EU (October = 10).
Value: 10
- See Also:
EU_START_YEAR,
Constant Field Values
EU_SWITCH_WEEKDAY
public static final int EU_SWITCH_WEEKDAY
- Start and end day of week for summer time in EU (Sunday = 0).
The switching occurs on the last EU_SWITCH_WEEKDAY at
EU_SWITCH_HOUR:00:00.000 within the EU_START_MONTH and
EU_END_MONTH.
Value: 0
- See Also:
EU_START_YEAR,
Constant Field Values
EU_SWITCH_HOUR
public static final int EU_SWITCH_HOUR
- Start- and and hour for summer time in EU (02:00).
Remark: At the end of summer time, the politicians did not choose to
prolong the end of Saturday having 24:00:00.000 to 24:59:59.000 as an
uniquely numbered extra time of day.
The choice of using Sunday 02:00:00 instead, gives us the time
02:00:00.000 to 02:59:59.000 twice. There is no uniform (standardised,
supported) way to handle this in parsing and formatting.
One aspect of the problem is:
If you see (in an EU time zone) "25.10.2009 01:31:53" or
"25.10.2009 03:31:53", you implicitly know if this is
daylight saving by the algorithm (EU rule; yes and no in this case).
But in the case of "25.10.2009 02:31:53" you don't. Some
process control systems than use something like
"25.10.2009 02A:31:53" and "25.10.2009 02B:31:53" for
logging. Other field of applications use other habits, most of them being
an nightmare for parsing, (String sorting) and formating, and, of course,
none of them really supported by Java, PHP or whatever.
Value: 2
- See Also:
EU_START_YEAR,
Constant Field Values
DAYSin4YEARS
public static final int DAYSin4YEARS
- Days in four years (implying one of it being a leap year).
Value: 1461
- See Also:
- Constant Field Values
helpTimeHolder
public static final ThreadLocal<ModifTime> helpTimeHolder
- Time object for helpers.
This ThreadLocal's method get() returns
a ModifTime object that may be freely used in the calling thread
without any further synchronisation.
The ModifTime object returned by get()
is a TimeST with default (local) time zone.
RATE_CHOOSE
public static final Action[] RATE_CHOOSE
- Action list for duration or rates.
Languages:
- English, German,
- just partly Italian, French.
- See Also:
parseDuration(CharSequence)
ACTION_TZ0
public static final Action ACTION_TZ0
- Action for time zone offset 0 , UTC.
Action to set time zone (raw) offset to 0; like in UTC.
TIME_CHOOSE
public static final Action[] TIME_CHOOSE
- Action list for date and time of day.
- See Also:
parse(CharSequence),
main(String[])
formatSQL
public static String formatSQL(long time)
- Formatting of date and time in SQL format.
This method formats the point of time defined by the parameter in
the way defined by
ConstTime.toSqlString().
Hint: This method uses the thread local helper object returned by
helpTimeHolder.get(). Re-using this
helper object is explicitly recommended.
daysSince1Mrz68
public static int daysSince1Mrz68(int d,
int m,
int j)
- Calculate the days since 1 March 1968 .
- Parameters:
d - day in month, 1 .. max, but not restricted
(using d-=100 before would go 100 days before the given date).m - Month, 1..12, (other values are illegal and default to March of
year j or year j-1)j - full year like 1871, 1953, 1998, 2009, ...)
parse
public static long parse(CharSequence time)
throws IllegalArgumentException
- Get / parse a time from String representation.
Interpret a String as date / time of day (overview)
This method tries to interpret the String parameter as time, that is
date and / or time of day — h:m:s, h:m or h:m:s.ms —.
No time of day acts like 00:00:00.000
parse(CharSequence) and parse(CharSequence, boolean)
understands a big variety of (syntactically) different formats. Likewise
time zone offsets are understood in a variety of forms.
The parsed formats include those usual in (North-) America, Europe and
Germany, as well as some Internet and operating system formats as well as
those usual in version control systems (cvs[NT] and SVN; see
CVSkeys).
Should, in spite of this flexibility, all interpretation of the
parameter s fail, an clearly worded IllegalArgumentException is
thrown. In the case of success, the absolute UTC/Java milliseconds
(1.1.1968 based) are returned (see
getMillis()). This class as
application (see main(String[])) can be used to explore the
time parser.
Without any time zone settings in the parameter, the default zone of the
underlying runtime is assumed.
Many three or four letter time zone abbreviations are recognised, like
UTC, GMT / WET, CET / MEZ, BST / IST / WEST, CEST / MES, MST / PST, EDT,
CDT, MDT / PDT, HKT, VET and many more.
Furthermore every time zone may be given as offset to UTC by + or - in
the style of "Sat, 12 Aug 1995 13:30:00 +0430" (4 hours
30 minutes west of Greenwich) or
"Sat, 12 Aug 1995 13:30:00 +04:30".
A prefix GMT, UT or UTC
("Sat, 12 Aug 1995 13:30:00 GMT+0430")
or a prefix signifying the same offset (as often used by Internet
applications, like CET+01:00) is allowed.
Besides the numeric formats many keywords in English, French and German
(so far, and partly other languages) are correctly interpreted
for setting dates and or times like:
"Tagesende", "end-of-day", "fin-du-jour",
"Mittag", "noon", "midi",
"Mitternacht", "midnight", "minuit",
"heute", "today", "aujourd'hui",
"morgen", "tomorrow", "demain",
"gestern", "yesterday", "hier",
"vorgestern", "beforeyesterday avant-hier",
"vorvorgestern", "jetzt", "now",
"maintenant and some more.
All those keywords are not case sensitive and they may be abbreviated,
like "mañana" or "mañ", "mañ." as long as no
ambiguity arises by that.
Running this class as application without programm parameters
(java de.frame4j.utils.TimeHelper) shows all
understood time keywords of Frame4J's installed version.
Background
This method may a bit remind to the less flexible, yet extremely useful
long parse(String)
in java.util.Date.
java.util.Date.parse(String) was, since JDK1.1, deprecated, without
giving a real substitute — which java.text.DateFormat clearly is not
with respect to parsing.
This desideratum alone was inducement for the development of
de.a_weinert.Zeithelper.parse() — the predecessor in use for years.
This method has all abilities (but not all faults) of the then deprecated
Date.parse(), featuring much more flexibility.
Two fundamental assumptions — both wrong — govern all Java
format (java.text-) classes, inappropriately offered as substitute for
the deprecated Date.parse():
- The first is that formating and
analysing (parsing) are complementary procedures. This gives any Format
class the burden of being able to parse, ruled by a format String defined
grammar. This, often being not or hardly feasible, makes this classes
unnecessarily thick and throw away object hungry (even if parsing with a
given format is never asked for).
- The other is, that parsing is to be bound to just one language or
locale.
In the case of formating, of course, one often wants to control every
field of the output, its sequence, its language and so on (see
Time.toString(CharSeq/String)). Controlling the output "to the last
letter" means defining a unique format or pattern. On the other hand,
at parsing, you are perfectly within your rights when expecting, that
all unambiguous notations for the same values or states are
understood:
"15. Januar 2009 Mittag" and "2009-1-15 12:00" denote
the same date and time of day and should be (are here) understood so
without switching formats or locales.
Some accepted / parsed formats (examples)
Sat, 12 Aug 1995 13:21:00.321 GMT+1
Samst., 12.8.95 13:21 MEZ
Samstag 12. aug. 95 13:21 MEZ
Samedi, août 12 95 13:21 CET
Sat. 8/12/95 13:21 GMT+0100
Sat. 8/12/95 13:21 +0100
Aug. 12 95 11 PM +1
12 Aug 95 11 PM +1
Dienstag 13:46
jetzt
vorgestern
gestern mittag
now
yesterday noon
2200-02-28T09:30:11.100+01:00
2200-02-28T08:30:11.100Z
This is all understood as well as the same in some other sequences, parts
of it and so on.
Names of months, days of week and others are (so far) accepted in the
above mentioned languages, full length abbreviated and with and without
accents. Ambiguous abbreviations are illegal.
Days of week have to be written correctly or abbreviated in a way not to
be mixed up with abbreviated months or times zones; Saturday is wrong.
If a date (12.7.03) is given, nevertheless, the day of week is ignored as
redundant information. If there is no date, a given day of week denotes
the latest possible day in the past, i.e. 1 to 7 days back. This fits to
the habit of some file and mail programmes, to omit the date and just give
the day of week, if the mail or the modification date is less than eight
days back.
All key word are case insensitive (CET cet CeT).
Operation
The String s is processed left to right. White spaces, underline
_ and comma as well as all within braces ( ) has no significance besides
the separation of fields. Brace pairs can be embedded ( Co(mme)nt ). This
is a reminiscence (i.e. compatibility) to the late Date.parse(), that
— why on earth — did so.
Any sequence of digits 1..9 is interpreted as number.
Any sequence of character s up to the next separator or digit or sign
(+ -) is regarded as keyword, naming a month, a day of week, a relative
date, a time of day or a time zone offset.
This is used to sift out
- day
- month (number or name, abbreviation),
- year (0..69 becomes 2000..2069, 70..99 becomes 1979..1999,
+0 is just 0),
on one hand and, on the other side
- hour
- minute
- second
- part of second or millisecond 0..999
- day of week,
- time zone (offset).
Besides a perhaps ignored day of week, no part may explicitly or
implicitly given more than once and contradictory.
The interpretation of a number is ruled by surrounding signs and
indications already made; i.e. sequence and partly magnitude.
Points (.) lead to German standard interpretation day.month.year
tag.monat.jahr (in this sequence if no other info was present).
An unsigned number > 62 (except following seconds) will be taken as year.
(Limit of 62 is taking leap seconds into consideration). So a year
can have any position (2003/04/24).
Colons (:) lead to time of day interpretation hour:minute:second or
hour:minute:second.millisecond .
An AM or vormittags is ignored if an hour 1..12 is given.
A PM or nachmittags is accepted if the hour is in the range 1..12,
for 1..11 then 12 will be added to have (internally) the non-ambiguous
0..23 range.
If no year was given signs + - lead to the interpretation as year (- as
BC).
If a year was given signs + - lead to the interpretation as time zone
offset in the range of -16 .. +16 (hours) or in the four digit hour-minute
form (with or without separating colon :) that allow for exotic half (and
even quarter) hour offsets or in the two digit hour form.
Time zone offsets can be made redundantly by digits and time zone
abbreviations as long as they are not contradictory.
Besides those cases of AM, time zones and the ignored day of week,
all else redundancy like "12:00:00 noon" is an error, as are
most range violations. All errors give an expressive
IllegalArgumentException.
Keywords are understood in English, French, German, Italian and Spanish
(until January 2009). Spaces in keywords have to be replaced by hyphen
and accents may be omitted, examples: "l'après-midi" and
"l'apres-midi", "end-of-day", "août",
"aout"
Names of months and day of week are also understood in Portuguese and
Dutch.
This method is equivalent to
parse(time, false).
To do: Try to understand the non human readable ISO 8601 formats without
most field separators like 20991231T235959.9942 .
Hint: Executing this class as application by
java de.frame4j.util.TimeHelper
lists all understood keywords and names; see main(String[]).
Doing so with arguments tries to parse those as time.
- Parameters:
time - the string to be interpreted as a indication of time
- Returns:
- the absolute milliseconds since 1.1.1970 00:00:00 UTC.
- Throws:
IllegalArgumentException, - if time can't be parsed.
IllegalArgumentException- See Also:
ModifTime.setMillis(long),
set(int,,,),
Action,
TextHelper
parse
public static long parse(CharSequence time,
boolean endDay)
throws IllegalArgumentException
- Get / parse a time from String representation.
Description
This method is equivalent to parse(CharSequence)
with the extra possibility to specify the end of the day (near midnight)
as default if no time of day is given.
So with this method you can choose the default time of day either as
00:00:00.0 (endDay false) or 23:59:59.999 (endDay true).
Non regarding a leap second, the intervals "beginDay..endDay" of
two consecutive days adjoin without gap.
Hint: Having a keyword Tagesende, end-of-day oder fin-du-jour in the
parameter String would have the same effect as endDay == true without
giving time of day time.
- Parameters:
endDay - true: no time of day in time
defaults to 23:59:59.999time - the string to be interpreted as a indication of time
- Returns:
- the absolute milliseconds since 1.1.1970 00:00:00 UTC.
- Throws:
IllegalArgumentException, - if time can't be parsed.
IllegalArgumentException- See Also:
Action.selectedBy(CharSequence, boolean)
parseDuration
public static long parseDuration(CharSequence rate)
throws IllegalArgumentException
- Parsing a rate (or duration).
Syntax: [white space] number [white space] [unit] [white space]
Or: [white space] keyword [white space]
Unit: ms (default), s, m, h, d, w
for milliseconds (default) seconds, minutes, hours, days or weeks.
Keyword: "sekündlich", "secondly",
"minütlich", "minutely", "stündlich",
"hourly", "horaire", "ogni-ora",
"por-hora", " cada-hora", "täglich",
"dayly", "quotidien", "giornaliero",
"por-día", "por-dia", "wöchendlich",
"weekly", "hebdomadaire", "settimanale",
"semanal".
Number: Defined by
Long.decode().
Hint: months and years don't give a unique duration in the sense
of a constant frequency.
- Parameters:
rate - the duration or rate
- Returns:
- rate in ms.
- Throws:
IllegalArgumentException - if syntax problems.
appendDuration
public static StringBuilder appendDuration(StringBuilder bastel,
long dur)
- Format a duration or rate.
Returned syntax/form is: 2w3d5h12m30,123s or 987ms
Not applicable parts are omitted; a negative parameter will get a
leading - .
Hint: The form delivered by this method
appendDuration(StringBuilder, long) is not understood by the
parsing method parseDuration(CharSequence).
- Parameters:
bastel - the StringBuilder to append to. If null, it will be
generated with starting capacity 56.dur - duration or rate to format in ms
- Returns:
- bastel
msToJavaTime
public static long msToJavaTime(long msTimeStamp)
- Transform Microsoft time stamp (long, ns) to Java time (long, ms).
Microsoft's long time stamp in in nanoseconds and differs in start
time.
- See Also:
javaTimetoMS(long)
javaTimetoMS
public static long javaTimetoMS(long javaTime)
- Transform Java time (long, ms to Microsoft time stamp (long, ns).
- See Also:
msToJavaTime(long)
isLeapYear
public static boolean isLeapYear(int y)
- Leap year.
This method applies Gregorian rules for y > 1000.
haveSameRules
public static boolean haveSameRules(TimeZone a,
TimeZone b)
- Do two time zones have the same rules.
This method gives the result, that the documentation of
TimeZone.hasSameRules()
describes.
Background: Most, usually buggy, implementations in TimeZone
return false, even if all described conditions are perfectly
fulfilled. Hence this substitute.
- Returns:
- true if same offset and using daylight saving
displTimeZones
public static Appendable displTimeZones(StringBuilder bastel)
- Generate a display of all pre-fabricated time zones.
For there use in some methods this class features some pre-fabricated
zones. This method generates a readable and detailed list.
- Parameters:
bastel - StringBuilder to append to, generated if null
- Returns:
- bastel
- See Also:
main(String[])
main
public static void main(String[] args)
- Display some info about class, time zones, explore the parser etc.
If no arguments are given, this application displays info about time zones
and the keywords defined or understood by this classes parsers.
Any given arguments are used to demonstrate the date/time parser.
- Parameters:
args - date / time string to parse and redisplay- See Also:
parse(CharSequence)